Lister
- Opprette lister
- Funksjoner og operasjoner
- Indeksering og beskjæring
- Destruktive funksjoner
- Leting etter elementer
- Legge til elementer
- Fjerne elementer
- Løkker over lister
- Sortering og reversering
- Pakke ut en liste i variabler
- Konvertering mellom lister og strenger (split/join)
- Finn Feilene
- Turtle
Opprette lister
# To standard måter å opprette lister på
a = []
b = list()
print(type(a), len(a), a)
print(type(b), len(b), b)
print(a == b)
# Liste med ett element
a = ["foo"]
b = [42]
print(type(a), len(a), a)
print(type(b), len(b), b)
print(a == b)
# Lister med flere elementer
a = [2, 3, 5, 7, 11]
b = list(range(5))
# kan blande datatyper
c = ["foo", 42, True, None, ""]
print(type(a), len(a), a)
print(type(b), len(b), b)
print(type(c), len(c), c)
# Lister med variabelt antall elementer
a = ["foo"] * 5
b = list(range(5))
print(type(a), len(a), a)
print(type(b), len(b), b)
Funksjoner og operasjoner
a = [2, 3, 5, 2]
print("a = ", a)
print("len =", len(a))
print("min =", min(a))
print("max =", max(a))
print("sum =", sum(a))
# Et par forskjellige lister
a = [2, 3, 5, 3, 7]
b = [2, 3, 5, 3, 7] # lik til a
c = [2, 3, 5, 3, 8] # forskjellig fra a
d = [2, 3, 5] # prefix for a
print("a =", a)
print("b =", b)
print("c =", c)
print("d =", d)
print("------------------")
print("a == b", a == b)
print("a == c", a == c)
print("a != b", a != b)
print("a != c", a != c)
print("------------------")
print("a < c", a < c) # Sammenligning basert på første ulike element
print("d < a", d < a) # Prefiksen er "mindre enn"
# Konkatenering
a = [3, 4]
b = [8, 9]
print("a =", a)
print("b =", b)
print("a + b =", a + b)
# Repetisjon
print("a * 3 = ", a * 3)
Indexing og slicing
# Indeksering og slicing fungerer på samme måte som for strenger
a = [2, 3, 5, 7, 11, 13]
print("a =", a)
# Indeksering. Første indeks er 0.
print("a[0] =", a[0])
print("a[2] =", a[2])
# Negative indekser
print("a[-1] =", a[-1])
print("a[-3] =", a[-3])
# Slicing a[start:slutt] eller a[start:slutt:steg]
print("a[0:2] =", a[0:2])
print("a[1:4] =", a[1:4])
print("a[1:6:2] =", a[1:6:2])
Mutasjon og alias
I motsetning til datatyper vi har sett hittil, kan vi endre på en liste uten å opprette en ny verdi i minnet. Dette kaller vi å mutere listen.
# Opprett en liste
a = [2, 3, 4]
# La b være en variabel som referer til samme liste som a
# Siden a og b er to variabler som refererer til det samme muterbare
# objekt, kaller vi a og b for aliaser.
b = a
# Mutasjon (endring) av listen
a[0] = 99
b[1] = 42
print(a)
print(b)
Dersom to variabler refererer til samme muterbare objekt, kalles de for aliaser.
# Opprett en liste
a = [2, 3, 5, 7]
# Opprett et alias for listen
b = a
# Opprett en ny liste med de samme elementene
c = [2, 3, 5, 7]
# a og b er referanser til (/aliaser for) DEN SAMME listen
# c er en referanse til en annen, men LIK liste
print("først:")
print(" a == b:", a == b)
print(" a == c:", a == c) # == -operatoren sier om to verdier er LIKE
print(" a is b:", a is b) # is -operatoren sier om to verdier er DEN SAMME
print(" a is c:", a is c)
# Mutasjon av a endrer også b (DEN SAMME listen) men ikke c (en annen liste)
a[0] = 42
print("etter mutasjonen a[0] = 42")
print(" a =", a)
print(" b =", b)
print(" c =", c)
print(" a == b:", a==b)
print(" a == c:", a==c)
print(" a is b:", a is b)
print(" a is c:", a is c)
Destruktive funksjoner
En funksjon er destruktiv dersom den har sideeffekter som endrer en liste.
# En destruktiv funksjon er skrevet for å mutere en liste. Den trenger ikke returnere noe
def fill(a, value):
for i in range(len(a)):
a[i] = value
a = [1, 2, 3, 4, 5]
print("Først, a =", a)
fill(a, 42)
print("Etter fill(a, 42), a =", a)
En ikke-destruktiv funksjon vil ikke ha sideeffekter, og vi benytter oss av returverdien i stedet.
def destructive_remove_all(a, value):
while value in a:
a.remove(value)
def non_destructive_remove_all(a, value):
# Vanligvis skriver vi ikke-destruktive funksjoner ved å opprette
# en ny liste fra scratch, og jobber på den
result = []
for element in a:
if element != value:
result.append(element)
return result # ikke-destruktive funksjoner MÅ returnere svaret!
def alternate_non_destructive_remove_all(a, value):
# Vi kan også skrive en ikke-destruktiv funksjon ved å ta en kopi først, og så returnere kopien
kopi = a[:]
destructive_remove_all(kopi, value)
return kopi # ikke-destruktive funksjoner må uansett returnere!
a = [1, 2, 3, 4, 3, 2, 1]
print("Først")
print(" a =", a)
destructive_remove_all(a, 2)
print("Etter destructive_remove_all(a, 2)")
print(" a =", a)
b = non_destructive_remove_all(a, 3)
print("Etter b = non_destructive_remove_all(a, 3)")
print(" a =", a)
print(" b =", b)
c = alternate_non_destructive_remove_all(a, 1)
print("Etter c = alternate_non_destructive_remove_all(a, 1)")
print(" a =", a)
print(" c =", c)
Leting etter elementer
# Inneholder listen min verdi?
a = [2, 3, 5, 2, 6, 2, 2, 7]
print("a =", a)
print("2 in a =", (2 in a))
print("4 in a =", (4 in a))
# eller ikke?
print("2 not in a =", (2 not in a))
print("4 not in a =", (4 not in a))
# Hvor mange ganger opptrer min verdi?
a = [2, 3, 5, 2, 6, 2, 2, 7]
print("a =", a)
print("a.count(1) =", a.count(1))
print("a.count(2) =", a.count(2))
print("a.count(3) =", a.count(3))
# Hvor i listen befinner verdien seg, da?
# a.index(element) eller a.index(element, start)
a = [2, 3, 5, 2, 6, 2, 2, 7]
print("a =", a)
print("a.index(6) =", a.index(6))
print("a.index(2) =", a.index(2))
print("a.index(2,1) =", a.index(2,1))
print("a.index(2,4) =", a.index(2,4))
# Oj! Krasjer dersom elmentet ikke er der
a = [2, 3, 5, 2]
print("a =", a)
print("a.index(9) =", a.index(9)) # krasjer!
print("Vi kom visst ikke så langt...")
# Løsning: benytt (element in liste) først.
a = [2, 3, 5, 2]
print("a =", a)
if (9 in a):
print("a.index(9) =", a.index(9))
else:
print("9 er ikke der", a)
print("Hurra!")
Legge til elementer
Destruktive metoder for å legge til elementer:
# Vi oppretter en liste og gir den et alias. Alle endringer vi gjør her
# reflekteres i aliaset, hvilket betyr at endringene er destruktive
a = [2, 3]
alias = a
# Legg til på slutten med .append
a.append(7)
print(a) # [2, 3, 7]
# Legg til på en bestemt posisjon med .insert
a.insert(2, 42)
print(a) # [2, 3, 42, 7]
# Utvid listen med flere elementer på en gang med .extend eller '+='
b = [100, 200]
a.extend(b)
print(a) # [2, 3, 42, 7, 100, 200]
a += b
print(a) # [2, 3, 42, 7, 100, 200, 100, 200]
print()
print(alias) # [2, 3, 42, 7, 100, 200, 100, 200]
Ikke-destruktive operasjoner for å legge til elementer:
a = [2, 3]
# Legg til på slutten med +
b = a + [13, 17]
print(a)
print(b)
# Legg til midt inne i listen med slices
c = a[:1] + [42] + a[1:]
print(a)
print(c)
Destruktiv vs. ikke-destruktiv utvidelse
print("Destruktiv:")
a = [2, 3]
b = a # lager alias
a += [4]
print(a)
print(b)
print("Ikke-destruktiv:")
a = [2, 3]
b = a # lager alias
a = a + [4] # a viser til en ny liste, kun b viser tul den gamle
print(a)
print(b)
Fjerne elementer
Destruktive metoder for å fjerne elementer
a = [2, 3, 5, 3, 7, 6, 5, 11, 13]
print("a =", a)
# Fjerne første opptreden av et bestemt element
a.remove(5)
print("Etter a.remove(5), a=", a)
a.remove(5)
print("Etter enda en a.remove(5), a=", a)
# Fjerne det siste elementet i listen
item = a.pop()
print("Etter item = a.pop()")
print(" item =", item)
print(" a =", a)
# Fjerne et element på en bestemt indeks
item = a.pop(3)
print("Etter item = a.pop(3)")
print(" item =", item)
print(" a =", a)
Løkker over lister
# Iterasjon uten indeks
# Lister og strenger er begge samlinger, såkalte "itererbare" typer.
# Det betyr at vi kan benytte en for-løkke på dem direkte
a = [2, 3, 5, 7]
for item in a:
print(item)
# Iterasjon med indeks, ikke brukes ofte
a = [2, 3, 5, 7]
for index in range(len(a)):
print(f"a[{index}] =", a[index])
print("---")
# heller bruk enumerate når du trenger indexverdien
for index, item in enumerate(a):
print(f"a[{index}] =", item)
# IKKE FJERN ELLER LEGG TIL ELEMENTER TIL SAMME LISTE DU GÅR GJENNOM
# MED EN FOR-LØKKE! INDEKSER KRØLLER SEG TIL!(dette er ikke et problem
# for strenger, siden de ikke kan muteres)
a = [2, 3, 5, 3, 7]
print("a =", a)
# Mislykket forsøk på å fjerne alle 3'erne
for index in range(len(a)):
if (a[index] == 3): # vi krasjer her etter en stund
a.pop(index)
print("Hit kommer vi ikke")
# IKKE MUTER EN LISTE INNI EN FOR-LØKKE!
# Vil ikke krasje, men gjør heller ikke som vi forventer
a = [3, 3, 2, 3, 4]
print("a =", a)
# Mislykket forsøk på å fjerne alle 3'erne
def should_be_removed(x):
return x == 3
for item in a:
if should_be_removed(item):
a.remove(item)
print(a)
# Bedre: mutering i en while-løkke.
# Her har vi full kontroll på hvordan indeks endrer seg.
a = [2, 3, 5, 3, 7]
print("a =", a)
# Vellykket forsøk på å fjerne alle 3'erne
index = 0
while (index < len(a)):
if (a[index] == 3):
a.pop(index)
else:
index += 1
print("Huzza! a =", a)
# en kortere alternativ
a = [2, 3, 5, 3, 7]
while 3 in a:
a.remove(3)
print("a =", a)
Sortering og reversering
Destruktiv sortering og reversering
# Sortering
a = [7, 2, 5, 3, 5, 11, 7]
print("Først, a =", a)
a.sort()
print("Etter a.sort(), a =",a)
print("---")
# Reversering
a = [2, 3, 5, 7]
print("Først, a =", a)
a.reverse()
print("Etter a.reverse(), a =", a)
Ikke-destruktiv sortering og reversering
# Sortering
a = [7, 2, 5, 3, 5, 11, 7]
print("Først, a =", a)
b = sorted(a)
print("Etter b = sorted(a)")
print(" a =", a)
print(" b =", b)
print("---")
# Reversering
a = [2, 3, 5, 7]
print("Først, a =", a)
b = reversed(a)
c = list(reversed(a))
print("Etter b = reversed(a) og c = list(reversed(a))")
print(" a =", a)
print(" b =", b)
print(" c =", c)
print("Her er elementene i b:")
for x in b:
print(x, end=" ")
print()
print("Her er elementene i b en gang til (men hæ???):")
for x in b:
print(x, end=" ")
print()
print("---")
Pakke ut en liste i variabler
Gitt en liste kan du “pakke den ut” i variabler.
a = ["Florida", 15.4, "2022-09-16"]
place, temp, date = a
print(f"{place = }", f" {temp = }", f" {date = }", sep="\n")
Hvis listen er lang, kan du pakke opp kun de par første verdiene og la resten bli en ny liste. Operasjonen er ikke-destruktiv.
a = ["Florida", 15.2, 13.5, 17.2, 13.6, 14.2]
place, *temps = a
print(f"{a=}")
print(f"{place=}")
print(f"{temps=}")
eller de par første og de par siste. Variabelen med *
foran plukker opp resten i en ny liste.
a = ["Florida", "not interested", 15.2, 13.5, 17.2, 13.6, 14.2, "OK"]
place, _, *temps, last_temp, status = a
print(f"{a = }")
print(f"{place = }")
print(f"{_ = }")
print(f"{temps = }")
print(f"{last_temp = }")
print(f"{status = }")
Konvertering mellom lister og strenger (split/join)
# bruk list(s) for å konvertere en streng til liste med tegn
a = list("hurra!")
print(a) # ['h', 'u', 'r', 'r', 'a', '!']
# bruk s1.split(s2) for å konvertere en streng s1 til en liste
# med strenger, klippet opp langs s2'er inne i s1
a = "Hva holder du på med?".split(" ")
print(a) # ['Hva', 'holder', 'du', 'på', 'med?']
# bruk "".join(a) for å lime sammen/konkatenere en liste med strenger
print("".join(a)) # Hvaholderdupåmed?
# s.join(a) for å lime sammen med s som lime-streng
print(" ".join(a)) # Hva holder du på med?
print("--".join(a)) # Hva--holder--du--på--med?
Finn feilene
Her er et eksempel på ting som kan gå galt med lister.
Før du kjør koden, se om du finner alle feil. Prøv å kjøre koden. Endre sånn at koden går å kjøre.
a = ["xyz", "abc", 5.4, "z", True, 7, "Hei there"]
length = len(a)
print(a[length])
b = [12, 34, 1, 107, "14", 16, 19]
b.sort()
print(b)
#####
print("Returning coins:")
coins = [1, 5, 10, 20]
price = 24
payment = 50
# work out return coins
diff = payment - price
for c in coins:
while diff > c:
print(f"Returning kr.{c}")
diff -= c
Koden i slutten skal beregne vekslepenger som skal returneres ved en betaling. Det finnes 20-kr, 10-kr, 5-kr og 1-kr. Den skal returnere slik at man får så få mynter som mulig. For eksempel, om prisen er 24 kr og betalingen er 50 kr skal den returnere én 20-kr, én 5-kr og én 1-kr. Men noe er feil med koden sånn at den ikke gjør helt som den skal. Kan du endre sånn at den fungerer som den skal?
Turtle
Her er et eksempel til bruk av lister med turtle. Vi tegner en spiral ut fra to lister, en med vinkler og en med lengder.
Vi bruker python-funksjonen exit() et sted for å avslutte programmet om listene ikke har den samme lengden.
import turtle as t
# list of angles, list of lengths
angles = [90.0, 90.0, 90.0, 90.0, 90.0]
lengths = [100, 120, 150, 180, 300]
# loop over each item in the two lists
if len(angles) != len(lengths): # why have this here?
print("lists not same length")
exit() # stops the program
# we use this combined list to give instructions to the turtle to draw a square:
for i in range(len(angles)):
t.left(angles[i])
t.forward(lengths[i])
t.done()