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.