Uke 9 - Dict

Denne uken skal vi se på en ny datastruktur, dict, som er brukt ofte for å lagre strukturert data.

Først, les gjennom https://automatetheboringstuff.com/2e/chapter5/ frem til «Pretty Printing», og se på «Practice Questions 1-7»

Eksempler

Eksempel 1

Her er et eksempel på en dictionary i Python. I dette eksemplet sier den hvilket husdyr ulike personer har.

Last ned filen her: eksempel_2.py, og kjør koden. Er navnet ’keys’ eller ’values’ i pet? Er dyret ’keys’ eller ’values’ i pet?

Hva gjør koden pet['Alice']? Hva gjør koden pet['Xavier'] = 'Alien'? Hvorfor blir det feil i den siste linjen?

pet = {
    'Alice' : 'Dog',
    'Bob' : 'Cat',
    'Claire' : 'Stick insect',
    'Dan' : 'Crocodile',
    'Eve' : 'Elephant',
    'Fred' : 'Dolphin'
}

print('All pets',pet)

print(pet['Alice'])
print(pet['Eve'])

pet['Xavier'] = 'Alien'

print(pet)

print(pet['Karl']) # KeyError

Eksempel 2

Vi kan bruke .keys(), .values() og .items() sammen med en for-løkke.

Last ned filen her: eksempel_3.py, og kjør koden.

Hva looper vi over når vi bruker en for-løkke med .keys()? Hva om vi bruker .values()? Hva om vi bruker .items()?

Hva skjer i den siste løkken?

pet = {
    "Bob": "Cat",
    "Fred": "Dolphin",
    "Dan": "Crocodile",
    "Claire": "Stick insect",
    "Alice": "Dog",
    "Eve": "Elephant",
}

print("All owners")
for name in pet.keys():
    print(name)

print("\n\n\n")

print("All pets")
for animal in pet.values():
    print(animal)

print("\n\n\n")

print("All pairs")
for p in pet.items():
    print(p)

print("\n\n\n")

print("Unpack the pair tuple")
for name, animal in pet.items():
    print(f"{name} has a pet, and it is a {animal}")

Eksempel 3

Vi kan bruke alle ’immutable data types’ som keys i en dictionary. Husker du hvilke datatyper er immutable?

I eksemplet her bruker vi heltall.

Last ned filen her: eksempel_4.py. Hva gjør koden?

Kjør koden og se om det var riktig.

Hvordan ser number_name ut på slutten av kjøringen?

number_name = {
    0 : 'zero',
    1 : 'one',
    2 : 'two',
    3 : 'three',
    12: 'twelve',
    10: 'ten',
}



def print_name(n):
    if n in number_name:
        print(f'{n} is called {number_name[n]}')
    else:
        print(f"I don't know what {n} is called.")
        name = input("Please tell me: ")
        number_name[n] = name

print_name(3)
print_name(56)

print_name(2)
print_name(56)

Eksempel 4

En dictionary kan f.eks brukes for å holde rede på hvor mange vi har av forskjellige ting. Her bruker vi dictionaries til å telle hvor mange ganger vi bruker ulike bokstaver og ord i begynnelsen av ’Alice in Wonderland’.

Last ned filen her: eksempel_5.py, og kjør koden. Skjønner du hva som skjer? Hva gjør .setdefault()? (Du kan lese om den i Pythons dokumentasjon.)

I slutten av koden finner vi de 5 vanligste ordene. Prøv å bruk ’option 2’ i stedet. Som vanlig kan du finne informasjon om hvordan sorted() fungerer i Pythons dokumentasjon.

Obs

Husk fra den forrige uken at du kan bruke søkeordargumenter med funksjonene dine og Pythons innbygde funksjoner, f.eks sorted()

Last ned filen her: eksempel_1.py, og kjør koden. Denne eksemplen er med lister, men du kan også bruke med dictionarys.

names = ['Alice', 'Bob', 'Claire', 'Dan', 'Eve', 'Fred']

# sort names by length
sorted_names = sorted(names, key=len)

print(sorted_names)

Se også i koden på variabelen sorted_result – dette er en smart bruk av søkeordargumenter for å sortere dictionarien din.

text = """Alice was beginning to get very tired of sitting by her sister
            on the bank, and of having nothing to do: once or twice she had peeped
            into the book her sister was reading, but it had no pictures
            or conversations in it, 'and what is the use
            of a book,' thought Alice 'without pictures or conversation?'"""

        
letter_count = {}

for l in 'abcdefghijklmnopqrstuvwxyz':
    letter_count[l] = 0

for let in text:
    let = let.lower()
    if let in letter_count: # check if key exists in dict
        letter_count[let] += 1
    
for let, count in letter_count.items():
    print(f'{let} is used {count:3d} times')

    
print('\n\n\n')


word_count = {}

for word in text.split():
    word = word.lower()
    word_count.setdefault(word, 0)
    word_count[word] += 1

for w, count in word_count.items():
    print(f'{w:14} is used {count:3d} times')


print('\n\n\n')

# The 5 most used words
# need to sort by the value in the (key,value) tuple

# option 1
def get_second(tpl):
    """Return the second element"""
    return tpl[1]

# using the keyword arguments of sorted() to sort by the second value and in reverse
sorted_result = sorted(word_count.items(), key=get_second, reverse=True)


# option 2, python has "get_second" built-in as "itemgetter"
#from operator import itemgetter
#sorted_result = sorted(word_count.items(), key=itemgetter(1), reverse=True)

print('The 5 most common words')
for w, c in sorted_result[:5]:
    print(f'{w:14} is used {c:3d} times')

Oppgaver

Oppgave 1

Lag en handleliste og print den. Handlelisten skal være en dict med varer som keys og antall som values. Varene er:

2 brød
3 pizza
10 poteter
1 kaffe
1 ost
14 epler

Skriv ut dictionarien:

{'brød': 2, 'pizza': 3, 'poteter': 10, 'kaffe': 1, 'ost': 1, 'epler': 14}

Oppgave 2

I denne oppgaven skal vi jobbe med my_dict og my_list definert her:

my_dict = {
  0 : 0,
  1 : "vafler",
  "two" : 2,
  5 : 4
}

my_list = [0, 1, "boller", 4]

Skriv ut nøklene, verdiene og nøkkel/verdi-par for my_dict, og listeverdiene og index/verdi par for my_list.

Eksempelkjøring:

Dictionary Keys:
0
1
two
5

Dictionary Values:
0
vafler
2
4

Dictionary keys/value:
0 0
1 vafler
two 2
5 4

List values:
0
1
boller
4

List indices/value:
0 0
1 1
2 boller
3 4

Oppgave 3

Vi ser for oss at følgende dictionary representerer varebeholdningen i en bokhandel. Nøklene er titler og verdiene er antall bøker:

in_storage = {
    "Ancillary Justice": 1_046, # vi kan bruke _ i tall, den blir ignorert
    "The Use of Weapons": 372,
    "1984": 5_332,
    "The Three-Body Problem": 523,
    "A Fisherman of the Inland Sea": 728,
}

Spør brukeren om en boktittel og bruk .get() for å finne ut hvor mange eksemplarer av boka vi har. Hvis boka ikke er på lager skal du skrive ut 0. Kjør løkken frem til vi får en tom streng som tittel.

Eksempelkjøring:

Tittel: 1984
Vi har 5332 av "1984"

Tittel: A Fire Upon the Deep
Vi har 0 av "A Fire Upon the Deep"

Tittel: Automate the Boring Stuff with Python
Vi har 0 av "Automate the Boring Stuff with Python"

Tittel:
Ha det!

Oppgave 4

Bruk funksjonen collatz_sequence fra uke 8 oppgave 2 til å lage en dictionary med tallene 1-10 som keys og Collatz-sekvensen som verdi. Print resultatet.

Her er én løsning på collatz_sequence:

def collatz_sequence(n):
    sequence = [n]
    while n > 1:
        if n % 2 == 0:
            n = n // 2
        else:
            n = 3*n + 1
        sequence.append(n)
    return sequence

Eksempelkjøring:

{1: [1], 2: [2, 1], 3: [3, 10, 5, 16, 8, 4, 2, 1], 4: [4, 2, 1], ...}

Oppgave 5

I denne oppgaven skal vi gjøre det samme som i oppgave 3, men litt annerledes. Hvis brukeren spør om en bok som ikke er på lager skal vi «kjøpe inn» 10 og legge til boka i in_storage med 10 eksemplarer.

Eksempelkjøring:

Tittel: 1984
Vi har 5332 av "1984"

Tittel: Automate the Boring Stuff with Python
Vi har 10 av "Automate the Boring Stuff with Python"

Tips: bruk setdefault()

Oppgave 6

I denne oppgaven skal vi bruke en dictionary med informasjon om biler:

cars = {
    "Escort" : {
        "Brand": "Ford",
        "Horsepower": 200,
        "Wheels": 4,
        "Color": "red"
    },
    "Beetle" : {
        "Brand": "Volkswagen",
        "Horsepower": 120,
        "Wheels": 4,
        "Color": "blue"
    },
    "Isetta" : {
        "Brand": "BMW",
        "Horsepower": 50,
        "Wheels": 3,
        "Color": "green"
    },
}

Bruk dette til å skrive ut merket, modellnavn, antall hjul, hestekrefter og farge for hver bil.

Eksempelkjøring:

The Ford Escort has:
4 wheels, 200 horsepowers, and is red

The Volkswagen Beetle has:
...

Oppgave 7

Fantasy Game Inventory fra boken (https://automatetheboringstuff.com/2e/chapter5/)

Du lager et fantasy-videospill. Datastrukturen for å modellere spillerens beholdning skal være en dictionary hvor nøklene er strings som beskriver tingene i beholdningen, og verdiene er integers som forteller hvor mange av hver ting som spilleren har. For eksempel, verdiene i dictionary {'rope': 1, 'torch': 6, 'gold coin': 42, 'dagger': 1, 'arrow': 12} betyr at spilleren har 1 rope, 6 torches, 42 gold coins, etc.

Begynne med filen uke09_oppgave_7.py og skriv resten av funksjonen displayInventory() som tar inn alle mulige beholdningene og printer dem som nedenfor. Funksjonen skal også returnere totalt antall.

Eksempelkjøring:

Inventory:
1 rope
6 torch
42 gold coin
1 dagger
12 arrow
Total number of items: 62

Oppgave 8

Dragon Hoard fra boken (https://automatetheboringstuff.com/2e/chapter5/)

Skatten til en beseiret drage er representert som en liste med strenger som dette: dragonLoot = ['gold coin', 'dagger', 'gold coin', 'gold coin', 'ruby']

Fyll inn funksjonen som heter addToInventory(inventory, addedItems), hvor inventory parameteren er en dictionarien av spillerens beholdning og addedItems parameteren er en liste som f.eks dragonLoot.

addToInventory() funksjonen burde returnere en dictionary som representerer den oppdaterte beholdningen. Merk at listen over tilleggsartikler kan inneholde flere av samme element.

Begynne med filen uke09_oppgave_8.py og skriv resten av funksjonen som heter addToInventory.

Om du kaller displayInventory() etter å ha oppdatert beholdingen med addToInventory() funksjonen skal du få ut likt som nedenfor:

Eksempelkjøring:

Inventory:
45 gold coin
1 rope
1 dagger
1 ruby
Total number of items: 48

Oppgave 9 - Euler 17

https://projecteuler.net/problem=17

If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.

If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?

NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20 letters. The use of «and» when writing out numbers is in compliance with British usage.

Skriv en funksjon number_name(N) som tar inn et heltall (opp til 1000) som argument N og returnerer det engelske navnet til tallet som en streng.

Tips: begynn med dict’et som finnes i eksempel 3, og legge inn flere tall der. Du trenger ikke å ta med alle tallene frem til 1000, siden de fleste kan settes sammen. Gjerne bruk flere funksjoner for å organisere programmet

Skriv en funksjon all_numbernames(N) som tar inn et heltall (opp til 1000) som argument N og returnerer den summerte lengden av alle navnene fra 1 til N (sjekk eksemplene fra Euler-teksten). Du kan gjenbruke number_name() her.

Skriv en funksjon solve_euler_17() som returnerer den summerte lengden av alle navnene fra 1 til 1000. Du kan gjenbruke de andre funksjonene.