# Dictionaries

# - Dictionaries speichern Schlüssel-Wert-Paare
# - beliebige Objekte als Werte nutzbar
# - Schlüssel müssen aber unveränderliche Objekte sein

d = {
  'auto' : 'car',
  'baum' : 'tree',
  'tür'  : 'door',
}

d['raum'] = 'ROom' # legt hier ein neues Schlüssel-Wert-Paar an
print(d)
d['raum'] = 'room' # ändert den Wert für den existierenden Schlüssel "raum"
print(list(d.keys()))     # Liste der Schlüssel
print(list(d.values()))   # Liste der Werte
print(list(d.items()))    # Liste der Schlüssel-Wert-Paare (Tupel)

d[(1,2)] = 'Tupel als Key'
# Liste als Key geht nicht!
# d[[1,2]] = 'Liste als Key'
# TypeError: unhashable type: 'list'

# erstes und drittes Feld (Kennzeichen und UID) der ersten 5 Zeilen der
# /etc/passwd in einem Dictionary speichern
d = dict(line.split(':')[:3:2] for line in list(open('/etc/passwd'))[:5])
#d = dict(line.split(':')[:3:2] for line in open('/etc/passwd').readlines()[:5])

# Iteration über den Schlüsseln des Dictionarys
#for nkz in d: print('%-20s%06d' % (nkz, int(d[nkz])))
for nkz in d: print(f'{nkz:<20}{int(d[nkz]):06}')
print()

# mittels Iterator die Schlüssel-Wert-Paare (Tupel) des Dictionarys durchlaufen
# und diese dabei gleich entpacken
#for nkz, uid in d.items(): print('%-20s%06d' % (nkz, int(uid)))
for nkz, uid in d.items(): print(f'{nkz:<20}{int(uid):06}')
print()

if 'root' in d: print(d['root']) # Test auf Schlüssel 'root'
del d['root']                    # Schlüssel 'root' löschen
if 'root' in d: print(d['root']) # ohne Test käme hier ein KeyError: 'root'
print(d.get('root'))             # bei get() kommt dagegen kein NameError, es liefert None oder
print(d.get('root', -1))         # einen Vorzugswert (hier -1) bei fehlendem Schlüssel 'root'
print()

# leeres Dictionary
d = {}

users = 'root', 'anton', 'root', 'berta'

for nkz in users:
    # im Dictionary zählen, wie oft ein Wort vorkommt; die Wörter dienen als
    # Schlüssel, der Wert ist die Anzahl
    d[nkz] = d.get(nkz, 0) + 1
print(d)

from collections import defaultdict, Counter

# bequemer mit defaultdict
dd = defaultdict(int)
for nkz in users:
    dd[nkz] += 1
print(dd)

# noch bequemer mit Counter
cnt = Counter(users)
print(cnt)

# die Wörter nochmal zählen (Update des Counters)
cnt.update(users)

# Dictionary Comprehension
d = {x: x*x for x in range(5)}
print(d)

d1 = {x : x**2 for x in range(1, 10)}
# {1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

d2 = {x : x**3 for x in range(4)}
# {0: 0, 1: 1, 2: 8, 3: 27}

# Dictionary Updates
d.update(Marta=23, Emma=77)
d = dict(d, Otto=88, Adam=43)
d.update([('Jutta', 44), ('Jens', 17)])
d.update((('Max', 99), ('Moritz', 100)))
d.update((x, x + 1) for x in range(2))     # mit Generatorausdruck
print(d)

# Dictionaries mischen (ab Python 3.5)
d3 = {**d1, **d2}
# {1: 1, 2: 8, 3: 27, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81, 0: 0}

d4 = {1: 1111, 2: 2222, **d1} # d1 == d4
d4 = {**d1, 1: 1111, 2: 2222}
# {1: 1111, 2: 2222, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}

# die Menge der Key beider Dictionaries
s = {*d1, *d2}
# {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
