Naloge

Delali bomo s tviti. Ti so shranjeni v seznamih, ki izgledajo takole.

["sandra: Spet ta dež. #dougcajt",
 "berta: @sandra Delaj domačo za #programiranje1",
 "sandra: @berta Ne maram #programiranje1 #krneki",
 "ana: kdo so te @berta, @cilka, @dani? #krneki",
 "cilka: jst sm pa #luft",
 "benjamin: pogrešam ano #zalosten",
 "ema: @benjamin @ana #split? po dvopičju, za začetek?"]

Zapis tvita se začne z imenom avtorja (brez @), sledi dvopičje, nato pa besedilo tvita.

  1. Napišite funkcijo unikati(s), ki prejme seznam nekih stvari in kot rezultat vrne nov seznam, v katerem se vsak element pojavi le enkrat. Vrstni red v rezultat naj bo enak vrstnemu redu prvih pojavitev v podanem seznamu. Klic unikati([1, 3, 2, 1, 1, 3, 2]) mora vrniti [1, 3, 2].

    Rešitev

    Najpreprosteje je sestaviti nov seznam in zlagati vanj. Preden dodamo posamezni element pa preverimo, ali je morda že v seznamu.

    def unikati(s):
        t = []
        for i in s:
            if i not in t:
                t.append(i)
        return t
    

  2. Napišite funkcijo avtor(tvit), ki vrne ime avtorja podanega tvita. Klic avtor("ana: kdo so te @berta, @cilka, @dani? #krneki") vrne "ana".

    Rešitev

    Razbijemo glede na dvopičje in vrnemo prvi element.

    def avtor(tvit):
        return tvit.split(":")[0]
    

  3. Napišite funkcijo vsi_avtorji(tviti), ki prejme seznam tvitov in vrne seznam vseh njihovih avtorje. Vsak naj se v seznamu pojavi le enkrat; vrstni red naj bo enak vrstnemu redu prvih pojavitev. Če funkcijo pokličemo z gornjim seznamom tvitov, mora vrniti ["sandra", "berta", "ana", "cilka", "benjamin", "ema"]. Sandra se pojavi le enkrat, čeprav je napisala dva tvita.

    Rešitev

    Pomagajte si s funkcijami, ki ste jih že napisali.

    def vsi_avtorji(tviti):
        imena = []
        for tvit in tviti:
            imena.append(avtor(tvit))
        return unikati(imena)
    

    Kmalu se bomo naučili, da gre tudi tako

    def vsi_avtorji(tviti):
        return unikati(map(avtor, tviti))
    

  4. Napišite funkcijo izloci_besedo(beseda), ki prejme neko besedo in vrne to besedo brez vseh ne-alfanumeričnih znakov (to je, znakov, ki niso črke ali števke) na začetku in koncu. Če pokličemo izloci_besedo("!%$ana---"), mora vrniti "ana". Če pokličemo izloci_besedo("@janez-novak!!!"), vrne "janez-novak" (in ne "janeznovak"!).

    Namig: strip() tule morda ne bo preveč uporaben. Pač pa v dokumentaciji Pythona preverite, kaj dela metoda isalnum. Potem nalogo rešite tako, da odstranjujte prvi znak besede, dokler ta ni črka. In potem na enak način še zadnjega. Kako besedi odstranimo znak, pa boste - če se ne boste spomnili sami - izvedeli v zapiskih o indeksiranju.

    Rešitev

    Najpreprostejša rešitev je: odbijamo prvi znak, dokler nam ni všeč. In potem odbijamo zadnji znak, dokler nam ni všeč. Nato vrnemo rezultat.

    def izloci_besedo(beseda):
        while beseda and not beseda[0].isalnum():
            beseda = beseda[1:]
        while beseda and not beseda[-1].isalnum():
            beseda = beseda[:-1]
        return beseda
    

    Drug, za računalnik hitrejši, a za nas zamudnejši način je, da najdemo indeks prve in zadnje črke ter vrnemo, kar je vmes.

    def izloci_besedo(beseda):
        for prva in range(len(beseda)):
            if beseda[prva].isalnum():
                break
        for zadnja in range(len(beseda), 0, -1):
            if beseda[zadnja-1].isalnum():
                break
        return beseda[prva:zadnja]
    

    Prvi del je lažji: zanko vrtimo, dokler ne pridemo do prve črke. Drugi je podoben, le indeksi so bolj zoprni: šli bomo od dolžine besede do 0 in preverjali en znak pred tem indeksom. Tako se splača zato, ker potem vrnemo vse znake do tega indeksa, se pravi vključno s tistim, ki smo ga preverjali.

  5. Napišite funkcijo se_zacne_z(tvit, c), ki prejme nek tvit in nek znak c. Vrniti mora vse tiste besede iz tvita, ki se začnejo s podanim znakom c. Pri tem mora od besed odluščiti vse nealfanumerične znake na začetku in na koncu. Klic se_zacne_z("sandra: @berta Ne maram #programiranje1 #krneki", "#") vrne ["programiranje1", "krneki"].

    Rešitev

    Sestavimo prazen seznam, gremo čez besede v tvitu, in v seznam zložimo vse, ki se začnejo s podanim znakom. Mimogrede pa pokličemo še izloci_besedo.

    def se_zacne_z(tvit, c):
        besede = []
        for beseda in tvit.split():
            if beseda[0] == c:
                besede.append(izloci_besedo(beseda))
        return besede
    

    Naučili pa se bomo tudi krajše.

    def se_zacne_z(tvit, c):
        return [izloci_besedo(beseda) for beseda in tvit.split() if beseda[0] == c]
    

  6. Napišite funkcijo zberi_se_zacne_z(tviti, c), ki je podobna prejšnji, vendar prejme seznam tvitov in vrne vse besede, ki se pojavijo v njih in se začnejo s podano črko. Poleg tega naj se vsaka beseda pojavi le enkrat. Če pokličemo zberi_se_zacne_z(tviti, "@") (kjer so tviti gornji tviti), vrne ['sandra', 'berta', 'cilka', 'dani', 'benjamin', 'ana']. Vrstni red besed v seznamu je enak vrstnemu redu njihovih pojavitev v tvitih.

    Rešitev

    To je spet podobno: sestavimo seznam, gremo čez tvite in zlagamo vanj. Edina razlika je, da moramo tokrat uporabiti += (ali extend) namesto append-a, saj lepimo skupaj sezname.

    def zberi_se_zacne_z(tviti, c):
        afne = []
        for tvit in tviti:
            afne += se_zacne_z(tvit, c)
        return unikati(afne)
    

  7. Napišite funkcijo vse_afne(tviti), ki vrne vse besede v tvitih, ki se začnejo z @. Če ji podamo gornje tvite, mora vrniti ['sandra', 'berta', 'cilka', 'dani', 'benjamin', 'ana'].

    Rešitev

    def vse_afne(tviti):
        return unikati(zberi_se_zacne_z(tviti, "@"))
    

  8. Napišite funkcijo vsi_hashtagi(tviti). Za gornje tvite vrne ['dougcajt', 'programiranje1', 'krneki', 'luft', 'zalosten', 'split'].

    Rešitev

    def vsi_hashtagi(tviti):
        return unikati(zberi_se_zacne_z(tviti, "#"))
    

  9. Napišite funkcijo vse_osebe(tviti), ki vrne po abecedi urejen seznam vseh oseb, ki nastopajo v tvitih - bodisi kot avtorji, bodisi so omenjene v tvitih. Vsaka oseba naj se pojavi le enkrat. Za gornje tvite funkcija vrne ['ana', 'benjamin', 'berta', 'cilka', 'dani', 'ema', 'sandra'].

    Rešitev

    Funkcija mora vrniti tisto, kar vrneta funkciji vsi_avtorji in vse_afne, le unikate moramo pobrati in vse skupaj urediti.

    def vse_osebe(tviti):
        osebe = unikati(vsi_avtorji(tviti) + vse_afne(tviti))
        osebe.sort()
        return osebe
    

    Če vemo za funkcijo sorted, pa gre še hitreje.

    def vse_osebe(tviti):
        return sorted(unikati(vsi_avtorji(tviti) + vse_afne(tviti)))
    

  10. Napišite funkcijo custva(tviti, hashtagi), ki prejme seznam tvitov in seznam hashtagov (brez začetnega #). Vrne naj vse avtorje, ki so uporabili vsaj enega od naštetih tagov. Avtorji naj bodo urejeni po abecedi in vsak naj se pojavi le enkrat. Klic custva(tviti, ["dougcajt", "krneki"]) vrne ["ana", "sandra"].

    Rešitev

    def custva(tviti, hashtagi):
        avtorji = []
        for tvit in tviti:
            if neprazen_presek(se_zacne_z(tvit, "#"), hashtagi):
                avtorji.append(avtor(tvit))
        avtorji.sort()
        return unikati(avtorji)
    

    Za vsak tvit preverimo, ali je presek med besedami, ki se začnejo s # in podanimi hashtagi neprazen. Če je tako, dodamo avtorja tega tvita v seznam avtorjev, ki ga posortiramo in vrnemo.

    Manjka nam še funkcija za neprazen presek?

    def neprazen_presek(s, t):
        for e in s:
            if e in t:
                return True
        return False
    

    Naučili pa se bomo tudi tako

    def custva(tviti, hashtagi):
        return unikati(sorted(avtor(tvit) for tvit in tviti if set(hashtagi) & set(se_zacne_z(tvit, "#"))))
    

  11. Napišite funkcijo se_poznata(tviti, oseba1, oseba2), če je oseba1 v katerem od svojih tvitov omenila osebo oseba2 ali obratno.

    Rešitev Gremo prek vseh tvitov. Za vsakega odkrijemo avtorja in vse, ki so omenjeni. Če je prva oseba pisec, druga pa omenjena ali pa obratno, vrnemo True. Če se to ne zgodi v nobenem tvitu, vrnemo False.

    def se_poznata(tviti, oseba1, oseba2):
        for tvit in tviti:
            pisec = avtor(tvit)
            omenjeni = se_zacne_z(tvit, "@")
            if oseba1 == pisec and oseba2 in omenjeni or \
                    oseba2 == pisec and oseba1 in omenjeni:
                return True
        return False
    

Last modified: Friday, 13 November 2020, 12:45 PM