LEKCJA 9 – SŁOWNIKI

 

W trzech omówionych dotąd typach sekwencji – listach, krotkach i napisach – dostęp do dowolnego elementu możliwy był poprzez podanie jego indeksu. Odmiennego rodzaju typem złożonym jest słownik (ang. dictionary). W słowniku dostęp do dowolnej wartości przechowywanej w słowniku możliwy jest poprzez podanie klucza do niej.

Słownik składa się zatem ze zbioru kluczy i zbioru wartości, gdzie każdemu kluczowi przypisana jest pojedyncza wartość. Zależność między kluczem a jego wartością nazywana bywa odwzorowaniem. Klucz nie musi być liczbą, tak jak jest nią indeks, wystarczy, że jest typu niezmiennego. Można powiedzieć więc, że o ile lista czy krotka odwzorowuje liczby całkowite (indeksy) na obiekty dowolnego typu, o tyle słownik odwzorowuje obiekty dowolnego typu niezmiennego na obiekty dowolnego typu.

W języku Python do tworzenia słowników używamy nawiasów klamrowych, np.:

 

>>> tel = {"policja":997, "straz":998, "pogotowie":999}

>>> tel

{'policja': 997, 'pogotowie': 999, 'straz': 998}

 

Klucze nie muszą być tekstem, a wartości liczbami:

 

>>> bohater={"hans":"kloss","james":"bond"}

>>> ujemne={7:-7,3:-3}

 

Specyficzny słownik zwraca funkcja vars( ). Zawiera on wszystkie dostępne aktualnie zmienne:

 

>>> vars()

{'tel': {'policja': 997, 'pogotowie': 999, 'straz': 998}, 'bohater': {'hans': 'kloss', 'james': 'bond'}, '__builtins__': <module '__builtin__' (built-in)>, 'ujemne': {3: -3, 7: -7}, '__name__': '__main__', '__doc__': None}

 

Aby ustalić ilość kluczy pamiętanych w słowniku używamy funkcji len:

 

>>> len(tel)

3

           

Aby otrzymać wartość podanego klucza używamy nawiasów kwadratowych:

 

>>> tel ["policja"]

997

>>> bohater["hans"]

'kloss'

>>> ujemne[7]

-7

 

Zwróćmy uwagę, że ujemne[7] nie oznacza siódmego elementu słownika, lecz taki element słownika, którego klucz stanowi liczba 7.

 

Aby dopisać nowy klucz:

 

>>> tel["taxi"]=919

>>> tel

{'taxi': 919, 'policja': 997, 'pogotowie': 999, 'straz': 998}

 

Aby zmodyfikować istniejącą wartość:

 

>>> tel["taxi"]=9622

>>> tel["taxi"]

9622

 

Zapis

 

>>> tel2=tel

 

nie skopiuje zawartości tel do tel2 ale jedynie stworzy drugie odwołanie do tych wartości. A zatem operacja

 

>>> tel2["taxi"]=9666

 

zmieni zarówno wartości tel jak i tel2, gdyż są to te same dane pod dwoma różnymi nazwami:

 

>>> tel

{'taxi': 9666, 'policja': 997, 'pogotowie': 999, 'straz': 998}

 

Aby skopiować zawartość jednego słownika do drugiego używamy metody copy:

 

>>> tel2=tel.copy()

 

W ten sposób otrzymaliśmy dwa różne słowniki, początkowo o tych samych wartościach.

 

>>> tel["taxi"]=9622

>>> tel

{'taxi': 9622, 'policja': 997, 'pogotowie': 999, 'straz': 998}

>>> tel2

{'taxi': 9666, 'policja': 997, 'pogotowie': 999, 'straz': 998}

 

Aby usunąć wartość ze słownika używamy instrukcji del:

 

>>> del tel['taxi']

>>> tel

{'policja': 997, 'pogotowie': 999, 'straz': 998}

 

Aby wyczyścić cały słownik używamy metody clear:

 

>>> tel.clear()

>>> tel

{}

 

Aby zaktualizować słownik w oparciu o inny słownik używamy metody update:

 

>>> tel.update(tel2)

>>> tel

{'taxi': 9666, 'policja': 997, 'pogotowie': 999, 'straz': 998}

 

Aby odczytać i od razu usunąć określoną wartość ze słownika używamy metody pop:

 

>>> tel.pop('taxi')

9666

>>> tel

{'policja': 997, 'pogotowie': 999, 'straz': 998}

 

Aby odczytać i od razu usunąć nieokreśloną wartość ze słownika używamy metody popitem:

 

>>> tel.popitem()

('policja', 997)

>>> tel

{'pogotowie': 999, 'straz': 998}

 

Aby sprawdzić zawartość określonego klucza w słowniku używamy operatora in:

 

>>> 'taxi' in tel

False

>>> 'taxi' in tel2

True

 

Można też użyć w tym celu metody has_key:

 

>>> tel2.has_key("pogotowie")

True

 

Aby uzyskać listę kluczy występujących w słowniku, używamy metody keys:

 

>>> tel.keys()

['pogotowie', 'straz']

 

Aby uzyskać listę wartości występujących w słowniku, używamy metody values:

 

>>> tel.values()

[999, 998]

 

Można w ten sposób sprawdzić występowanie określonych wartości:

 

>>> 999 in tel.values()

True

 

Aby skonwertować słownik na napis:

 

>>> str(tel2)

"{'taxi': 9666, 'policja': 997, 'pogotowie': 999, 'straz': 998}"

 

Aby usunąć cały słownik:

 

>>> del tel

>>> tel

 

Traceback (most recent call last):

  File "<pyshell#35>", line 1, in -toplevel-

    tel

NameError: name 'tel' is not defined

 

Przykład 1. Napisz program „liczby_slownie.py”, który zamieni podaną przez użytkownika zapisaną słownie wartość  (z zakresu od 1 do 59) na odpowiadającą jej liczbę dziesiętną.

Plan programu. Słowny zapis wartości składa się z sekwencji słów (np. trzydzieści trzy), z których każdemu przypisana jest pewna wartość. Wartość odpowiadającą całemu zapisowi otrzymuje się ze zsumowania wartości poszczególnych słów (np. trzydzieści (30) trzy (3) = 30 +3 = 33). Program powinien zatem rozbić wprowadzony przez użytkownika napis (raw_input) na wyrazy składowe (split), dla każdego wyrazu (for x in l) oznaczającego wartość (if x in w) ustalić odpowiadającą mu wartość (w[x]), a następnie dodać je do siebie (s+=w[x]).

Kod źródłowy:

 

def przelicz(n=""):

    w={"jeden":1, "dwa":2, "trzy":3, "cztery":4, "pięć":5, "sześć":6,

       "siedem":7, "osiem":8, "dziewięć":9, "dziesięć":10, "jedenaście":11,

       "dwanaście":12, "trzynaście":13, "czternaście":14, "piętnaście":15,

       "szesnaście":16, "siedemnaście":17, "osiemnaście":18,

 "dziewiętnaście":19, "dwadzieścia":20, "trzydzieści":30,

 "czterdzieści":40, "pięćdziesiąt":50}

    l=n.split()

    s=0

    for x in l:

       if x in w:

           s+=w[x]

    return s

 

t=raw_input("Wpisz liczbę od 1 do 59>")

print "Wartość:", przelicz(t)

 

Przykłady działania:

 

>>> ================================ RESTART ==============================

>>>

Wpisz liczbę od 1 do >czterdzieści trzy

Wartość: 43

>>> ================================ RESTART ==============================

>>>

Wpisz liczbę od 1 do 59>dwadzieścia siedem

Wartość: 27

>>> ================================ RESTART ==============================

>>>

Wpisz liczbę od 1 do 59>bla bla dwa

Wartość: 2

 

Przykład 2. Napisz program „liczby_rzymskie.py”, który zamieni całkowitą liczbę dziesiętną na odpowiadającą jej liczbę rzymską.

Plan programu. Liczby rzymskie składają się z ciągu liter, z których każda oznacza pewną wartość (np. M – 1000, D – 500, C100, L – 50), a które dodane do siebie dadzą wartość reprezentowanej liczby. Liczbę zapisuje się możliwie najkrócej, czyli używa się liter o maksymalnej możliwej wartości. Litery oznaczające większe wartości umieszcza się przed tymi oznaczającymi mniejsze (czyli ML oznacza 1050), są jednak od tej reguły wyjątki, np. 900 zapisuje się jako CM, a nie DCCCC.

Gdy chcemy zamienić całkowitą liczbę dziesiętną na odpowiadającą jej liczbę rzymską musimy najpierw ustalić pierwszą literę liczby rzymskiej. Będzie nią największa wartość, która jest nie mniejsza od konwertowanej liczby. Kiedy tę wartość ustalimy, zapamiętujemy odpowiadającą jej literę, a samą wartość odejmujemy od konwertowanej liczby. Kiedy skonwertujemy ostatnią jedynkę (I), oznaczać to będzie, że liczba została w całości skonwertowana – można więc wyświetlić wynik.

Do zapamiętania wszystkich znanych wartości liter w liczbach rzymskich wykorzystamy słownik (rzym). Jego kluczami będą wartości liter, a wartościami odpowiadające im litery. Słownik obejmował będzie również wszystkie wyjątki.

Program zacznie działanie od wczytania liczby do skonwertowania (x). Następnie stworzymy listę wartości liter (r) uporządkowaną malejąco poprzez wydobycie listy kluczy ze słownika (rzym.keys), rosnące jej posortowanie (r.sort), a wreszcie odwrócenie kolejności (r.reverse). Ciąg zawierający wynik konwersji (lr) inicjalizujemy jako pusty.

Następnie, dla każdej wartości i z listy r, tak długo jak jest ona większa lub równa pozostałej do konwersji liczbie x, odpowiadającą jej sekwencję liter (rzym[i]) dołączamy do ciągu wynikowego (lr), a samą wartość odejmujemy (x -= i) od liczby pozostałej do konwersji.

Po zakończeniu powyższej pętli, wyświetlamy rezultat konwersji (print lr).

Kod źródłowy:

 

rzym = { 1000:"M", 900:"CM", 500:"D", 400:"CD", 100:"C", 90:"XC", 50:"L",

         40:"XL", 10:"X", 9:"IX", 5:"V", 4:"IV", 1:"I" }

 

x = input("Podaj liczbę całkowitą:")

print "Liczba",`x`,"w notacji rzymskiej to:",

r = rzym.keys()

r.sort()

r.reverse()

lr = ""

for i in r:

    while i <= x:

        lr += rzym[i]

        x -= i

print lr

 

Przykład uruchomienia (F5):

 

>>> ================================ RESTART =============================

>>>

Podaj liczbę całkowitą:13

Liczba 13 w notacji rzymskiej to: XIII

>>> ================================ RESTART =============================

>>>

Podaj liczbę całkowitą:1097

Liczba 1097 w notacji rzymskiej to: MXCVII

 

Ćwiczenia kontrolne

Ćwiczenie I. Napisz program „liczby_slownie2.py”, który dla wprowadzonej liczby dziesiętnej (z zakresu 1-1999) wyświetli jej wartość zapisaną słownie.

Ćwiczenie II. Napisz program „liczby_rzymskie2.py”, który przeliczy wprowadzoną liczbę rzymską na jej postać dziesiętną.