Uke 9 - Dict / Files¶
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»
Vi skal også lese data fra en fil for første gang her. Se på Section 7.2 og 7.2.1 i Python Tutorial: https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files
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_1.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_2.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. For eksempel kan vi bruke heltall.
Last ned filen her: eksempel_3.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',
}
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’.
Du finner informasjon om modulen string
i Pythons dokumentasjon.
Last ned filen her: eksempel_4.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.
from string import ascii_lowercase
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 ascii_lowercase: # abcd...z
letter_count[l] = 0
for let in text:
let = let.lower()
if let in letter_count:
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]
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')
Eksempel 5¶
I dette eksemplet skal vi prøve å lese og skrive til en fil. Du må laste ned denne
tekstfilen: timemachine.txt
Last ned filen her: eksempel_5.py, og kjør koden. Hva er forskjellen mellom
for line in f, f.readlines() og f.read() for å lese fra filen?
Hva skjer når du åpner filen ’numbers.txt’ med mode ’w’ i slutten?
# 3 ways of getting information from a file
with open('timemachine.txt', encoding="utf8") as f:
for line in f:
l = len(line)
print('The line is',l,'long, and starts with')
print('>>>',line[0:20],'<<<')
# ========
with open('timemachine.txt', encoding="utf8") as f:
all_lines = f.readlines()
print(len(all_lines),'lines in the text')
# ==========
with open('timemachine.txt', encoding="utf8") as f:
all_lines = f.read()
print("vvvvvvv")
print(all_lines)
print("^^^^^^^")
# ========
with open('numbers.txt', 'w', encoding="utf8") as f:
for i in range(100):
f.write(f'{i} is a nice number\n')
# now open the file numbers.txt in your editor and see what's inside
# write other files!
Eksempel 6¶
I dette eksempelet teller vi hvor mange ganger ulike bokstaver og ord blir brukt i hele boken ’Alice in wonderland’. Derfor vil vi lese in teksten fra en fil, istedet for å lime hele teksten inn i filen med python-kode.
Til dette eksemplet må du laste ned denne tekstfilen: alice.txt.
Koden er i denne filen: eksempel_6.py. Kjør koden. Skjønner du hva som skjer?
from string import ascii_lowercase
with open('alice.txt', encoding="utf8") as f:
text = f.read()
letter_count = {}
for l in ascii_lowercase:
letter_count[l] = 0
for let in text:
let = let.lower()
if let in letter_count:
letter_count[let] += 1
for let, count in letter_count.items():
print(f'{let} is used {count:5d} times')
print('\n\n\n')
word_count = {}
for word in text.split():
word = word.lower()
word_count.setdefault(word, 0)
word_count[word] += 1
def get_second(tpl):
return tpl[1]
sorted_result = sorted(word_count.items(), key=get_second, reverse=True)
N = 15
print(f'The {N} most common words')
for w, c in sorted_result[:N]:
print(f'{w:14} is used {c:5d} times')
Oppgaver¶
..note:
Gå gjennom denne ukens innhold før du begynner!
Du får din kopi av oppgavene på git.app.uib.no. Oppgavene skal leveres ved push til det repoet innenfor 2020-10-23 23:59. Du kan pushe så mange ganger du vil før fristen og du får automatisk tilbakemelding hver gang.
Del 1 - 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)
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)
Skriv en funksjon solve_euler_17() som returnerer den summerte lengden av alle navnene fra 1 til 1000
Del 3 - Havnivå 1¶
Du skal ikke bruke ``import`` her, men du kan legge til flere hjelpefunksjoner
I filen VIK_sealevel_2000.txt finnes målinger av havnivået på et sted, hvor
en linje i filen representerer én måling, repetert for hver time i året 2000.
Det finnes 8784 linjene i alt, og formatet er
year month day hour height[cm]
Skriv en funksjon read_file(filename) som tar et filnavn av en slik datafil som argument og returnerer en liste av tuples med 5 heltall. I vårt eksempelfil begynner og slutter listen slik:
[
(2000, 1, 1, 1, 335),
(2000, 1, 1, 2, 336),
(2000, 1, 1, 3, 338),
# ...
(2000, 12, 31, 22, 337),
(2000, 12, 31, 23, 338),
(2000, 12, 31, 24, 339)
]
Alle følgende funksjonene tar inn denne listen som argument.
Skriv en funksjon average(data, month=None) som tar inn datalisten
og et argument month med standardverdi None. Hvis month er None,
skal funksjonen returnere gjennomsnittet av alle målingene. Hvis month er gitt
som et tall 1-12, skal funksjonen returnere gjennomsnittet av alle målingene
i den tilsvarende måneden.
Skriv en funksjon add_weekday(data) som tar inn datalisten og returnerer an ny dataliste
med 6 kolonner. Den 6. kolonnen skal inneholde ukedag som en streng (Sat Sun Mon Tue Wed Thu Fri).
2000-01-01 var en lørdag (Sat), 2000-12-31 var en søndag (Sun).
For eksempeldatasettet ser returnverdien slik ut:
[
(2000, 1, 1, 1, 335, 'Sat'),
(2000, 1, 1, 2, 336, 'Sat'),
(2000, 1, 1, 3, 338, 'Sat'),
# ...
(2000, 12, 31, 22, 337, 'Sun'),
(2000, 12, 31, 23, 338, 'Sun'),
(2000, 12, 31, 24, 339, 'Sun')
]
Skriv en funksjon average_weekday(data, weekday) som tar inn den utvidete datalisten
og et argument weekday som er en av strengene Sat Sun Mon Tue Wed Thu Fri.
Funksjonen skal returnere gjennomsnittet av alle målingene for tilsvarende ukedagen.
Del 4 - Havnivå 2¶
Du skal ikke bruke ``import`` her, men du kan legge til flere hjelpefunksjoner*
Skriv en funksjon max_indexes(xs) som tar inn en liste xs med tall,
og returnerer en liste av indeksposisjoner hvor listen har lokale maksimalverdier.
Et lokalt maksimum er et tall i listen som har mindre tall før og etter.
F.eks har denne listen et lokalt maksimum på posisjon 2 og 7:
[3, 4, 5, 2, 1, 0, 4, 6, 4, 2, 1]
. *** ***
Funksjonen skal returnere [2, 7] her. Om flere verdier er like, returnerer vi
den siste indexposisjonen: Input [2,3,3,1] har output [2].
Bruk denne funksjonen sammen med read_file(filename) funksjonen og datasett
fra del 3 for å finne ut gjennomsnittsavstand mellom to høyvann-episoder. Du kan strukturere
koden fritt, slik som du trenger.