From 236001ec7563804f87a40c924681461bc8b2d764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Mo=C5=BEina?= Date: Mon, 5 Dec 2016 11:51:58 +0100 Subject: Added a new set of exercises (regular expressions). --- python/problems/dictionaries/dict_sl.html | 598 ++++++++++++++++++++++++++++++ 1 file changed, 598 insertions(+) create mode 100644 python/problems/dictionaries/dict_sl.html (limited to 'python/problems/dictionaries') diff --git a/python/problems/dictionaries/dict_sl.html b/python/problems/dictionaries/dict_sl.html new file mode 100644 index 0000000..8b7966d --- /dev/null +++ b/python/problems/dictionaries/dict_sl.html @@ -0,0 +1,598 @@ + + + + + + + + + + +

Slovar

+ +

Poglejmo še enkrat sezname. Seznam je nekakšna zbirka nekih poljubnih + reči, pri čemer je vsaka reč v svojem "predalčku", predalčki pa so + oštevilčeni. Prvi ima številko 0, drugi 1, tretji 2 in tako naprej. Za + vsak predalček lahko pogledamo, kaj je v njem, spremenimo njegovo vsebino, + predalčke lahko odvzemamo in dodajamo. + +

>>> s = [6, 9, 4, 1]
+>>> s[1]
+9
+>>> s.append(7)
+>>> s
+[6, 9, 4, 1, 7]
+>>> del s[3]
+>>> s
+[6, 9, 4, 7]
+>>> s[-2:]
+[4, 7]
+ +

Slovar (angl. dictionary, podatkovni tip pa se imenuje + dict) je podoben seznamu, le da se na predalčke sklicujemo z + njihovimi ključi (angl. key, ki so lahko števila, lahko + pa tudi nizi, logične vrednosti, terke... Temu, kar je shranjeno v predalčku + bomo rekli vrednost (value).

+ +

Seznam in slovar se že od daleč (če niste kratkovidni) razlikujeta po + oglatosti. Seznam smo opisali tako, da smo v oglatih oklepajih + našteli njihove elemente. Slovar opišemo tako, da v zavitih + oklepajih naštejemo pare ključ: vrednost. + +

Stalno omenjani Benjamin si lahko takole sestavi slovar s telefonskimi + številkami svojih oboževalk: +

stevilke = {"Ana": "041 310239", "Berta": "040 318319", "Cilka": "041 103194", "Dani": "040 193831",
+                "Eva": "051 123123", "Fanči": "040 135367", "Helga": "+49 175 4728 475"}
+ +

Do vrednosti, shranjenih v slovarju, pride podobno kot do vrednosti v + seznamu: z indeksiranjem, le da v oglate oklepaje ne napiše zaporedne + številke, temveč ključ.

+ +
>>> stevilke["Ana"]
+'041 310239'
+>>> stevilke["Dani"]
+'040 193831'
+ +

Slovarji ne poznajo vrstnega reda. V slovarju ni prvega, drugega, tretjega + elementa. Ne le zato, ker oznake niso številke. Ne, slovar si v resnici ne + zapomni vrstnega reda, v katerem smo našteli elemente, niti ne vrstnega + reda, v katerem jih dodajamo.

+ +
>>> stevilke
+{'Dani': '040 193831', 'Fanči': '040 135367', 'Helga': '+49 175 4728 475',
+'Eva': '051 123123', 'Cilka': '041 103194', 'Berta': '040 318319',
+'Ana': '041 310239'}
+ +

(Čemu?! Čemu je to potrebno? Čemu zmeša vrstni red?! Mar ne more zlagati + teh reči lepo po vrsti? Izvedeli boste drugo leto. V resnici ni zmešan, + temveč prav premeteno premetan. V tem, drugače preurejenem seznamu lahko išče + veliko hitreje.)

+ +

Ker ni vrstnega reda, tudi ni rezin.

+ +
>>> stevilke["Ana":"Cilka"]
+Traceback (most recent call last):
+  File "", line 1, in 
+TypeError: unhashable type
+ +

Tole sporočilo o napaki je sicer zelo čudno, vendar povsem smiselno. Boste +razumeli, ko boste veliki. ;)

+ +

O "mehaniki" slovarjev morate vedeti le tole: slovarji so hitri, saj + elementov v resnici ne iščejo. Na nek za zdaj skrivnosten način "vedo", kje + je vrednost, ki pripada danemu ključu. Ne da bi iskali, vedo, kam morajo + pogledati. Tudi dodajanje novih elementov v slovar je zelo hitro, enako tudi + brisanje. Cena, ki jo plačamo za to, je dvojna. Ključi so lahko le + podatkovni tipi, ki so nespremenljivi. Nespremenljivi podatkovni tipi so, + vemo, nizi, števila, logične vrednosti in terke. Zgoraj smo kot ključ + uporabili niz. To je OK. Če bi poskušali kot ključ uporabiti seznam, ne bi + šlo. (V resnici je stvar malenkost bolj zapletena, ključ je lahko vsak + podatkovni tip, ki je "razpršljiv", vendar to ni za bruce). Omejitve + veljajo le za ključe. Vrednost je lahko karkoli.

+ +

Drugi obrok cene, ki jo plačamo za učinkovitost slovarjev, je poraba + pomnilnika: slovar porabi nekako dvakrat več pomnilnika kot seznam. Koliko, + točno, več, je odvisno od velikost slovarja in tega, kaj shranjujemo. + Pri tem predmetu se s pomnilnikom ne obremenjujte.

+ +

Aha, še tretji obrok cene, iz drobnega tiska: vsak ključ se lahko pojavi + največ enkrat. Če poskušamo prirediti neko vrednost ključu, ki že obstaja, le + povozimo staro vrednost. Ampak to je tako ali tako pričakovati. Tudi v + seznamu nimamo nikoli dveh različnih elementov na istem mestu.

+ +

Kaj lahko počnemo s slovarji?

+ +

Lahko jim dodajamo nove elemente: preprosto priredimo jim nov element.

+ +
>>> stevilke["Iva"] = "040 222333"
+>>> stevilke
+{'Dani': '040 193831', 'Fanči': '040 135367', 'Iva': '040 222333',
+'Helga': '+49 175 4728 475', 'Eva': '051 123123', 'Cilka': '041 103194',
+'Berta': '040 318319', 'Ana': '041 310239'}
+ +

append ne obstaja, saj nima smisla: ker ni vrstnega reda, ne +moremo dodajati na konec. Prav tako (ali pa še bolj) ne obstaja +insert, saj prav tako (ali pa še bolj) nima smisla. + +

Vprašamo se lahko, ali v seznamu obstaja določen ključ.

+ +
>>> "Cilka" in stevilke
+True
+>>> "Jana" in stevilke
+False
+ +

Če se Cilka skrega z Benjaminom, jo lahko le-ta pobriše (mislim, pobriše + njeno številko).

+ +
>>> del stevilke["Cilka"]
+>>> stevilke
+{'Dani': '040 193831', 'Fanči': '040 135367', 'Iva': '040 222333',
+'Helga': '+49 175 4728 475', 'Eva': '051 123123',
+'Berta': '040 318319', 'Ana': '041 310239'}
+>>> "Cilka" in stevilke
+False
+ +

Če gremo prek slovarjev z zanko for, dobimo vrednosti + ključev.

+ +
>>> for ime in stevilke:
+... 	print(ime)
+...
+Dani
+Fanči
+Iva
+Helga
+Eva
+Berta
+Ana

+ +Seveda lahko ob vsakem imenu izpišemo tudi številko. + +
>>> for ime in stevilke:
+... 	print(ime + ":", stevilke[ime])
+...
+Dani: 040 193831
+Fanči: 040 135367
+Iva: 040 222333
+Helga: +49 175 4728 475
+Eva: 051 123123
+Cilka: 041 103194
+Berta: 040 318319
+Ana: 041 310239
+ +

Vendar to ni najbolj praktično. Pomagamo si lahko s tremi metodami slovarja, + ki vrnejo vse ključe, vse vrednosti in vse pare ključ-vrednost. Imenujejo + se (ne preveč presenetljivo) keys(), values() in + items(). Delamo se lahko, da vračajo sezname ključev, + vrednosti oziroma parov ... čeprav v resnici vračajo le nekaj, prek česar + lahko gremo z zanko for. + +

Najprej poglejmo items().

+ +
>>> for t in stevilke.items():
+... 	ime, stevilka = t
+... 	print(ime + ":", stevilka)
+ +

Tole zgoraj je bilo seveda grdo. Lepo se reče takole:

+ +
>>> for ime, stevilka in stevilke.items():
+... 	print(ime + ":", stevilke)
+ +

Tako kot sem ob zanki for težil, da ne uporabljajte +for i in range(len(s)) temveč for e in s in da +že v glavi zanke razpakirajte terko, kadar je to potrebno, bom težil tudi +tule: uporabljajte items in vaši programi bodo preglednejši in +s tem pravilnejši.

+ +

Metoda values vrne vse vrednosti, ki so v slovarju. V našem + primeru torej telefonske številke. Metodo values človek včasih +potrebuje, prav pogosto pa ne.

+ +

V nasprotju s tem metodo keys potrebujejo samo študenti. Ne vem +točno, zakaj sploh obstaja. No, vem, zato da študenti lahko pišejo +for ime in stevilke.keys() namesto +for ime in stevilke. Druge uporabne vrednosti pa ne vidim. :)

+ +

Skratka: ne uporabljajte metode keys.

+ +

Slovar ima še dve metodi, ki smo ju videli tudi pri seznamu: metodo, ki + sprazni slovar in drugo, ki naredi nov, enak slovar.

+ +
>>> stevilke2 = stevilke.copy()
+>>> stevilke2
+{'Dani': '040 193831', 'Fanči': '040 135367', 'Iva': '040 222333',
+'Helga': '+49 175 4728 475', 'Eva': '051 123123',
+'Berta': '040 318319', 'Ana': '041 310239'}
+>>> stevilke.clear()
+>>> stevilke
+{}
+>>> stevilke2
+{'Dani': '040 193831', 'Fanči': '040 135367', 'Iva': '040 222333',
+'Helga': '+49 175 4728 475', 'Eva': '051 123123',
+'Berta': '040 318319', 'Ana': '041 310239'}
+ +

Omenimo le še eno od slovarjevih metod, get. Ta dela podobno + kot indeksiranje, stevilke.get("Ana") naredi isto kot + stevilke["Ana"]. Metodo get uporabimo, kadar ni + nujno, da je ključ v seznamu in želimo v tem primeru dobiti neko privzeto + vrednost. Privzeto vrednost podamo kot drugi argument.

+ +
>>> stevilke.get("Ema", "ni številke")
+'040 584928'
+>>> stevilke.get("Greta", "ni številke")
+'nimam stevilke'
+ +

Še enkrat: ne pišite stevilke.get("Ema"). To je čudno. +Piše se stevilke["Ema"]. Metodo get uporabite le +takrat, kadar niste prepričani, da slovar vsebuje ta ključ.

+ +

Primer: kronogrami

+ +

Neka naloga je šla takole.

+ +

Veliko latinskih napisov, ki obeležujejo kak pomemben dogodek, je napisanih + v obliki kronograma: + če seštejemo vrednosti črk, ki predstavljajo tudi rimske številke (I=1, V=5, + X=10, L=50, C=100, D=500, M=1000), dajo letnico dogodka.

+ +

Tako, recimo, napis na cerkvi sv. Jakoba v Opatiji, CVIVS IN HOC RENOVATA + LOCO PIA FVLGET IMAGO SIS CVSTOS POPVLI SANCTE IACOBE TVI, da vsoto 1793, + ko je bila cerkev prenovljena (o čemer govori napis).

+ +

Pri tem obravnavamo vsak znak posebej: v besedil EXCELSIS bi prebrali + X + C + L + I = 10 + 100 + 50 + 1 = 161 in ne + XC + L + I = 90 + 50 + 1 = 141.

+ +

Napiši program, ki izračuna letnico za podani niz.

+ +

Očitna rešitev je:

+ +
def kronogram(s):
+    v = 0
+    for c in s:
+        if c=="I":
+            v += 1
+        elif c=="V":
+            v += 5
+        elif c=="X":
+            v += 10
+        elif c=="L":
+            v += 50
+        elif c=="C":
+            v += 100
+        elif c=="D":
+            v += 500
+        elif c=="M":
+            v += 1000
+    return v
+ +

Pri njej vsi, ki poznajo stavek switch oz. case +postokajo, kako je možno, da Python tega stavka nima. (Pustimo ob strani, +ali je tole res toliko daljše od switch, sploh če program nespodobno +nabijemo skupaj:

+
def kronogram(s):
+    v = 0
+    for c in s:
+        if c=="I": v += 1
+        elif c=="V": v += 5
+        elif c=="X": v += 10
+        elif c=="L": v += 50
+        elif c=="C": v += 100
+        elif c=="D": v += 500
+        elif c=="M": v += 1000
+    return v
+

). Ne, nima ga, ker ga skoraj nikoli ne potrebujemo. Tisto, kar delamo z +njim, pogosto rešimo (tudi) s slovarji.

+ +

V slovar si bomo zapisali, katero številko pomeni katera črka.

+ +
stevke = {"I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000}
+ +

Funkcija zdaj deluje tako, da gre prek niza in za vsako črko preveri, ali je v +slovarju. Če je ni, ne pomeni številke; če je, prištejemo toliko, kolikor je +vredna.

+ +
def kronogram(s):
+    v = 0
+    for c in s:
+        if c in stevke:
+            v += stevke[c]
+    return v

+ +

Še hitreje gre z get; če črke ni, je njena privzeta vrednost 0. +

+
def kronogram(s):
+    v = 0
+    for c in s:
+        v += stevke.get(c, 0)
+    return v
+ +

Ob tem si ne moremo kaj, da ne bi poškilili za en mesec naprej, ko se bomo + učili funkcijskega programiranja in znali biti še krajši in jedrnatejši, + spet predvsem po zaslugi slovarjev.

+ +
def kronogram(s):
+    return sum(stevke.get(c, 0) for c in s)
+ + +

Slovarji s privzetimi vrednostmi

+ +

Slovarji so uporabne reči. V veliko primerih pa uporabimo neko različico +slovarja, ki ima še eno dodatno sposobnost.

+ +

Denimo, da smo dobili v preskušanje igralno kocko, za katero nas zanima, ali + goljufa. Stokrat smo jo vrgli in zabeležili rezultate.

+ +
meti = [4, 4, 4, 3, 2, 3, 5, 3, 3, 4, 6, 6, 6, 1, 3,
+        6, 6, 4, 1, 4, 6, 1, 4, 4, 4, 6, 4, 6, 5, 5, 6, 6, 2, 4, 4, 6,
+		3, 2, 6, 1, 3, 6, 3, 2, 6, 6, 4, 6, 4, 2, 4, 4, 1, 1, 6, 2, 6,
+		6, 4, 3, 4, 2, 6, 5, 6, 3, 2, 5, 1, 5, 3, 6, 4, 6, 2, 2, 4, 1,
+		4, 4, 3, 1, 4, 2, 1, 3, 1, 4, 6, 1, 1, 3, 4, 1, 4, 3, 2, 4, 6, 6]
+ +

Zanima nas, kolikokrat je padla katera številka. Nič lažjega. Najprej si + pripravimo seznam s sedmimi ničlami.

+ +
>>> kolikokrat = [0] * 7
+>>> kolikokrat
+[0, 0, 0, 0, 0, 0, 0]
+ +

Zdaj nam bo, recimo kolikokrat[3] povedal, kolikokrat je padla + trojka. (Čemu sedem? Saj ima kocka samo šest ploskev. Boste videli. Finta.) + Zdaj pa štejmo: pojdimo čez vse mete in povečujmo števce.

+ +
>>> for met in meti:
+... 	kolikokrat[met] += 1
+...
+>>> kolikokrat
+[0, 14, 12, 15, 27, 6, 26]
+ +

(Kje je finta? kolikokrat[0] bo pove, kolikokrat je padla ničla. +Nikoli pač. Napišite isto reč s seznamom dolžine šest, ne sedem. Ni problem, +ampak tako, kot smo nardili je preprostejše.)

+ +

(Kocka je res videti nekoliko sumljiva: štirke in šestice so nekam pogoste + na račun petk. A pustimo statistikom vprašanje, ali je to še lahko + naključno ali ne.)

+ +

Ups, nalogo smo rešili kar s seznamom! Da, to gre, ker so "predalčki" + seznama oštevilčeni, tako kot ploskve kocke. Tole pa ne bo šlo: tule je + seznam telefonskih številk deklet, ki jih je danes klical Benjamin. Katero + je poklical kolikokrat?

+ +
klici = ['041 103194', '040 193831', '040 318319', '040 193831', '041 310239',
+        '040 318319', '040 318319', '040 318319', '040 193831', '040 193831',
+        '040 193831', '040 193831', '040 193831', '040 318319', '040 318319',
+        '040 318319', '040 193831', '040 318319', '041 103194', '041 103194',
+        '041 310239', '040 193831', '041 103194', '041 310239', '041 310239',
+        '040 193831', '041 310239', '041 103194', '040 193831', '040 318319']
+ +

Za tako velike številke bi moral imeti seznam zelo veliko predalčkov. Še + huje bi bilo, če bi namesto seznama številk dobili seznam klicanih oseb.

+ +
klici = ['Cilka', 'Dani', 'Berta', 'Dani', 'Ana', 'Berta', 'Berta',
+         'Berta', 'Dani', 'Dani', 'Dani', 'Dani', 'Dani', 'Berta', 'Berta',
+         'Berta', 'Dani', 'Berta', 'Cilka', 'Cilka', 'Ana', 'Dani', 'Cilka',
+         'Ana', 'Ana', 'Dani', 'Ana', 'Cilka', 'Dani', 'Berta']
+ +

Tu smo s seznamom pogoreli. No, ne čisto; rešitev s seznami seveda obstaja, + je pa zoprna - podobna je tistemu, kar smo v začetku počeli z bančnimi + računi.

+ +

S slovarji je veliko lepše: +

pogostosti = {}
+for ime in klici:
+    if ime not in pogostosti:
+        pogostosti[ime] = 0
+    pogostosti[ime] += 1
+print(pogostosti)
+ +

Ob vsakem novem klicu preverimo, ali je klicano ime že v + slovarju. Če ga ni, da dodamo. Nato - najsibo ime novo ali ne - povečamo + števec klicev pri tej osebi.

+ + +

Ker je ta stvar resnično pogosta, nam Python pomaga z modulom +collections, ki vsebuje podatkovni tip defaultdict. +(Modul, ki vsebuje podatkovni tip?! Da, da; tudi to je ena od stvari, ki jih +bomo našli v modulih.) Ta se obnaša tako kot slovar, z eno izjemo: če zahtevamo +kak element, ki ne obstaja, si ga meni nič tebi nič izmisli. Točneje, doda ga v +slovar in mu postavi privzeto vrednost. Katero, določimo. Pri tem ne podamo +privzete vrednosti, temveč "funkcijo", ki bo vračala privzeto vrednost. +defaultdict bo ustvarjal te, nove vrednosti tako, da bo poklical +to funkcijo brez argumentov in kot privzeto vrednost uporabil, kar vrne +funkcija, ki jo v ta namen vsakič sproti pokliče.

+ +

Zelo pogosto bo privzeta vrednost 0 in funkcija, ki vrača + 0, se imenuje, hm, int.

+ +

("Funkcija" int, je vedno sumljivejša in sumljivejša. Že od +začetka smo v zvezi z njo dajali besedo "funkcija" pod narekovaje, zdaj pa vidimo, +da zmore vedno več in več stvari. Pa še enako ji je ime kot tipu in funkcij, ki +jim je ime enako kot tipom, je vedno več. Kakšna skrivnost se skriva za tem? To +boste izvedeli v enem od prihodnjih napetih nadaljevanj Programiranja 1.)

+ +

Preštejmo torej še enkrat Benjaminove klice, tokrat s slovarjem s privzetimi + vrednostmi.

+ +
import collections
+
+pogostosti = collections.defaultdict(int)
+for ime in klici:
+    pogostosti[ime] += 1
+ +

Ni to kul?

+ +

Poglejmo si nekaj, kar je kul še bolj.

+ + +

Števec

+ +

Preštevanje je pravzaprav tako pogosta reč, da obstaja zanj specializiran + tip. Tako kot defaultdict je v modulu collections, +imenuje pa se Counter.

+ +
>>> stevilo_klicev = collections.Counter(klici)
+>>> stevilo_klicev
+Counter({'Dani': 11, 'Berta': 9, 'Cilka': 5, 'Ana': 5})
+ +

Komentirali ne bomo veliko, ker še ne znamo. Že ob tem, da sem temu rekel + tip, sem se moral ugrizniti v jezik, saj bi raje govoril o razredu. Kaj je + in kako deluje, pa nas še presega. Zna pa pravzaprav še veliko stvari, + tako da tem, ki jih zanima, priporočam, da si ga ogledajo. Mimogrede:

+ +
>>> napis = "CVIVS IN HOC RENOVATA LOCO PIA FVLGET IMAGO SIS" \
+        "CVSTOS POPVLI SANCTE IACOBE TVI"
+>>> collections.Counter()
+Counter({' ': 13, 'I': 8, 'O': 8, 'V': 7, 'A': 6, 'C': 6, 'S': 6, 'T': 5, 'E': 4,
+'L': 3, 'N': 3, 'P': 3, 'G': 2, 'B': 1, 'F': 1, 'H': 1, 'M': 1, 'R': 1})
+ +

Se pravi, da lahko kronogram rešimo tudi z

+ +
def kronogram(s):
+    crke = collections.Counter(s)
+    return crke["I"] + 5 * crke["V"] + 10 * crke["X"] + 50 * crke["L"] + \
+           100 * crke["C"] + 500 * crke["D"] + 1000 * crke["M"]
+ + + +

Množice

+ +

Množice so podobne seznamom, a s to razliko, da lahko vsebujejo vsak element + samo enkrat. Po drugi strani (in ne le po drugi strani, tudi tehnično) pa + so podobne slovarjem. Niso namreč urejene in vsebujejo lahko le elemente, + ki so nespremenljivi. Poleg tega pa lahko zelo hitro ugotovimo, ali množica + vsebuje določen element ali ne - tako kot lahko pri slovarjih hitro + ugotovimo, ali vsebujejo določen ključ ali ne.

+ +

Množice zapišemo z zavitimi oklepaji, tako kot smo vajeni pri matematiki.

+
danasnji_klici = {"Ana", "Cilka", "Eva"}
+ +

Tako lahko sestavimo le neprazno množico. Če napišemo le oklepaj in + zaklepaj, {}, pa dobimo slovar. (Čemu so se odločili, naj bo + to slovar, ne množica? Slovar je bil prej, množice je Python dobil kasneje. + Zato.) Če hočemo narediti prazno množico, rečemo

+ +
prazna = set()
+ +

"Funkcija" set je malo podobna "funkciji" int: + damo ji lahko različne argumente, pa jih bo spremenila v množico. Damo ji + lahko, recimo, seznam, pa bomo dobili množico z vsemi elementi, ki se + pojavijo v njem.

+ +
>>> set([1, 2, 3])
+{1, 2, 3}
+>>> set(range(5))
+{0, 1, 2, 3, 4}
+>>> set([6, 42, 1, 3, 1, 1, 6])
+{1, 42, 3, 6}
+ +

Mimogrede opazimo, da tudi množice, tako kot slovarji, res ne dajo nič na + vrstni red.

+ +

Poleg seznamov lahko množicam podtaknemo karkoli, prek česar bi lahko šli + z zanko for, recimo niz ali slovar.

+ +
>>> set("Benjamin")
+{'a', 'B', 'e', 'i', 'j', 'm', 'n'}
+>>> stevilke
+{'Dani': '040 193831', 'Fanči': '040 135367', 'Iva': '040 222333',
+'Helga': '+49 175 4728 475', 'Eva': '051 123123', 'Cilka': '041 103194',
+'Berta': '040 318319', 'Ana': '041 310239'}
+>>> set(stevilke)
+{'Iva', 'Helga', 'Eva', 'Berta', 'Fanči', 'Dani', 'Cilka', 'Ana'}
+ +

Spremenljivka stevilke (še vedno) vsebuje slovar, katerega + ključi so imena Benjaminovih oboževalk. Ker zanka prek slovarja "vrača" + ključe, bo tudi množica, ki jo sestavimo iz slovarja, vsebovala ključe.

+ +

V množico lahko dodajamo elemente in vprašamo se lahko, ali množica vsebuje + določen element.

+ +
>>> s = set("Benjamin")
+>>> "e" in s
+True
+>>> "u" in s
+False
+>>> s.add("u")
+>>> s
+{'a', 'B', 'e', 'i', 'j', 'm', 'n', 'u'}
+>>> "u" in s
+True
+>>> s.add("a")
+>>> s.add("a")
+>>> s.add("a")
+>>> s
+{'a', 'B', 'e', 'i', 'j', 'm', 'n', 'u'}
+ +

Na koncu smo poskušali v množico dodati element, ki ga že vsebuje. To seveda + ne gre, množica vsak element vsebuje le enkrat.

+ +

Če imamo dve množici, lahko izračunamo njuno unijo, presek, razliko...

+ +
>>> u = {1, 2, 3}
+>>> v = {3, 4, 5}
+>>> u | v
+{1, 2, 3, 4, 5}
+>>> u & v
+{3}
+ +

Preverimo lahko tudi, ali je neka množica podmnožica (ali nadmnožica druge). + To najpreprosteje storimo kar z operatorji za primerjanje.

+ +
>>> u = {1, 2, 3}
+>>> {1, 2} <= u
+True
+>>> {1, 2, 3, 4} <= u
+False
+>>> {1, 2, 3} <= u
+True
+>>> {1, 2, 3} < u
+False
+ +

{1, 2, 3}, je podmnožica u-ja, ni pa njegove + prava podmnožica, saj vsebuje kar cel u.

+ +

Z množicami je mogoče početi še marsikaj zanimivega - vendar bodi dovolj.

+ + +

Primer: Seznami v slovarjih

+ +

Recimo, da želimo sestaviti skupine datotek v nekem direktoriju glede na + končnice. Sestavili bomo slovar, katerega ključi bodo končnice, na primer + .py, .txt in .mp3, vrednosti pri vsakem ključu pa imena datotek s to + končnico.

+ +
datoteke = {}
+for ime in os.listdir(dir):
+    konc = os.path.splitext(ime)[1]
+    if not konc in datoteke:
+        datoteke[konc] = set()
+    datoteke[konc].add(ime)
+ + +

Če ste bili pozorni, niste spregledali, da je gornji program pravzaprav na + nek način enak programu, s katerim smo preštevali, kolikokrat je Benjamin + klical katero od deklet: + +

pogostosti = {}
+for ime in klici:
+    if not ime in pogostosti:
+        pogostosti[ime] = 0
+    pogostosti[ime] += 1
+

+ +

"Istost" je v tem, da obakrat naredimo prazen slovar. Nato gremo z zanko +for čez neke reči. Za vsako reč (v gornjem primeru datoteke, v +spodnjem ime dekleta) preverimo, ali je že v slovarju. Če je ni, jo dodamo tako, +da ji damo neko privzeto vrednost (zgoraj prazno množico, spodaj 0). Nato +pravkar dodano stvar posodobimo glede na trenutno reč (v gornjem primeru dodamo +datoteko v pravkar sestavljeno ali od prej obstoječo množico, v spodnjem povečamo +število klicev te osebe za 1).

+ +

Aja, to finto pa že poznamo. Slovarji s privzetimi vrednostmi!

+ +
datoteke = collections.defaultdict(set)
+for ime in os.listdir(dir):
+    konc = os.path.splitext(ime)[1]
+    datoteke[konc].add(ime)
+ \ No newline at end of file -- cgit v1.2.1