# SLOWNIKI
# stowarzyszenia kluczy z wartosciami
# klucze stanowia zbior (nie powtarzaja sie, musza byc hashowalne)

# konstrukcja przez pary klucz: wartosc
d = {1 : 'a', 2 : 'b', 'abc' : [1,2,3], (1,2) : 1}
print(d[1]) # # wartosc stowarzyszona z kluczem 1, czyli 'a'
print(d[(1,2)]) # 1
d[1] = 'new text' # nowa wartosc dla klucza 1
print(d[1]) # 'new text'

# d[[1,2]] = 1 # TypeError: unhashable type: 'list'

del d[1] # usuniecia klucza 1 (i stowarzyszonej wartosci)|
print(d) # d == {2: 'b', 'abc': [1, 2, 3], (1, 2): 1}

# iteracja po kluczach:
for k in d:
    print(k)

# iteracja po wartosciach:
for v in d.values():
    print(v)

# iteracja po parach klucz, wartosc:
for k, v in d.items():
    print(k, v)

# schemat konstrukcji slownikow:
d = {n: n**2 for n in range(5)}

d1 = {1 : 'a', 2 : 'b', 3 : 'c'} # pewne przyporzadkowanie bijektywne ...
d2 = {v : k for k, v in d1.items()} # ... i odwrotne
print(d1, d2)

# pusty slownik:
d = {} # nie zbior

# konstrukcja slownika z ciagu par (kazda para staje sie para (klucz, wartosc)):
d = dict([(1,2), (2,3), "AB"])
print(d)

# konstrukcja slownika przez nazwane parametry (nazwy parametrow staja sie kluczami):
d = dict(k1='a', k2='b')
print(d)

# czy klucz jest w slowniku?
print(1 in d1)
print('b' in d2)
print('x' in d2)

#################
# BONUS: ZBIORY #
#################

# elementami zbiorow sa dowolne niezmienialne (scislej: hashowalne) obiekty
s = {1, 4, 5, 7, 8, "a", "b"} # konstrukcja: przez podanie elementow
s.add(1) # dodajemy 1: zbior pozostaje bez zmian
s.remove(4) # usuwamy 4: s == {1, 5, 7, 8, "a", "b"}

# konstrukcja przez podanie obiektu iterowalnego (np. napisu):
s = set("lokomotywa")
t = set("abcaca")

# operacje mnogosciowe
print("s={}, t={}".format(s, t))
print("suma s i t:", s | t)
print("roznica s i t:", s - t)
print("przekroj s i t:", s & t)
print("roznica symetryczna s i t:", s ^ t) # roznica symetryczna
print(s ^ t == (s - t) | (t - s)) # porownanie
print('l' in s) # operator nalezenia
# inne operacje - slajdy

# konstrukcja przez jako schemat:
s = {n**2 for n in range(5)}

# zbior pusty:
s = set() # nie {} - to jest slownik

# niezmienialny odpowiednik : frozenset
s = frozenset([1, 2, 3])
# s.update(4) - nielegalne
s |= {4} # legalne: to samo, co s = s | {4}
