2.16. Lister

Lister er variabler med nul til flere sammenhørende rum. Listen kendes på dens firkantede parenteser. Tænker du dig dem taget væk, har du en tuple. Den kendes på dens kommaer.

Listens og dens muligheder:
>>> # Opret tom liste
>>> listen = []
>>> # udvid listen med et ekstra element
>>> listen.append("Ypnasted")
>>> # udvidelsen kan også ske således:
>>> listen[len(listen):] = "Teglkaas"
>>> listen[len(listen):] = ["Hellig Peder"]
>>> listen
['Ypnasted', 'T', 'e', 'g', 'l', 'k', 'a', 'a', 's', 'Hellig Peder']
>>> # udvidelsen kan også ske således:
>>> listen.extend(["Vang","Hammeren"])
>>> listen
['Ypnasted', 'T', 'e', 'g', 'l', 'k', 'a', 'a', 's', 'Hellig Peder', 'Vang', 'Hammeren']
>>> # Listen kan vendes om:
>>> listen.reverse()
>>> listen
['Hammeren', 'Vang', 'Hellig Peder', 's', 'a', 'a', 'k', 'l', 'g', 'e', 'T', 'Ypnasted']
>>> # fjerner sidste element i listen:
>>> listen.pop()
'Ypnasted'
>>> listen
['Hammeren', 'Vang', 'Hellig Peder', 's', 'a', 'a', 'k', 'l', 'g', 'e', 'T']
>>> for i in range(0,8):
...     listen.pop()
...
'T'
'e'
'g'
'l'
'k'
'a'
'a'
's'
>>> listen
['Hammeren', 'Vang', 'Hellig Peder']
>>> # sorterer listen
>>> listen.sort()
>>> listen
['Hammeren', 'Hellig Peder', 'Vang']
>>> # fjerner angivne element fra listen:
>>> listen.remove("Hellig Peder")
>>> listen
['Hammeren', 'Vang']
>>> # returnerer givne indeks (plads) i listen
>>> listen.index("Hammeren")
0
>>> listen.index("Vang")
1
>>> # finder listens største element:
>>> max(listen)
'Vang'
>>> # finder listens mindste element:
>>> min(listen)
'Hammeren'
>>> # opdeler listen i enkeltelementer
>>> zip(listen,[1,2])
[('Hammeren', 1), ('Vang', 2)]
>>> zip(listen,[8,7])
[('Hammeren', 8), ('Vang', 7)]
>>> # multiplicerer listen:
>>> lister = listen * 2
>>> lister
['Hammeren', 'Vang', 'Hammeren', 'Vang']
>>> # multiplicerer listen:
>>> lister = zip(listen,[1,2]) * 2
>>> lister
[('Hammeren', 1), ('Vang', 2), ('Hammeren', 1), ('Vang', 2)]
>>>

Returnering af større eller mindre dele af en liste kaldes slicing. Slicing af en given del af en liste sker ved at indsætte start- og slutindeks i de fra listen velkendte firkantede parenteser:

>>> l = [1,2,3,3,4,5,6,7,8,9] >>> print l[0] # returner listens første element 1 >>> print l[0:4] # returner listens 4 første elementer [1, 2, 3, 3] >>> print l[3:6] # returner listens 4. til 6. element [3, 4, 5] >>> print l[-4] # returner listens 4. sidste element 6 >>> print l[-1] # returner listens sidste element 9 >>>

# Opret liste med lige tal <= 20 # Søg i liste efter integer (heltal) liste = range( 0, 21, 2 ) #listeindhold: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20] print liste skalFindes = int( raw_input( "Indtast heltal <= 20: " ) ) if skalFindes in liste: print "Fundet på indeks:", liste.index( skalFindes ) else: print "Elementet blev ikke fundet"

Indtast heltal <= 20: 12 Fundet på indeks: 6 Indtast heltal <= 20: 13 Elementet blev ikke fundet

Listen og tuplen har flere lighedspunkter: >>> l = [] >>> t = {} >>> t = 1,2,3,5 >>> t (1, 2, 3, 5) >>> l = t >>> l (1, 2, 3, 5) >>> l[1] 2 >>> t[1] 2 >>> l = [6,7,8,9] >>> l [6, 7, 8, 9] >>> t = l >>> t [6, 7, 8, 9]

liste = [] # opret tom liste # indsæt elementer i listen for indeks in range( 1, 11 ): liste += [ indeks ]

print "Listens indhold:", liste

print # indsætter tom linje

for element in liste: print element,

print

# listetilgang via indeks (rumnummer) print "\nVælg elementer efter deres indeks:" print "Listens indhold:"

for i in range( len( liste ) ): print "%6d %3d" % ( i, liste[ i ] )

print "\nOpdatering af listeelementer..." print "Listens indhold før opdateringen:", liste liste[ 0 ] = -100 liste[ -3 ] = "bornholmere" print "Listens indhold efter opdateringen:", liste

ajbo@linux:~> python anvendt_liste.py Listens indhold: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

1 2 3 4 5 6 7 8 9 10

Vælg elementer efter deres indeks: Listens indhold: 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10

Opdatering af listeelementer... Listens indhold før opdateringen: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Listens indhold efter opdateringen: [-100, 2, 3, 4, 5, 6, 7, 'bornholmere', 9, 10]

liste = [] # opretter tom liste

# indsæt 10 heltal via brugerindtastninger print "Skriv 10 heltal:"

for i in range( 10 ): nytElement = int( raw_input( "Skriv helt tal: %d: " % ( i + 1 ) ) ) liste += [ nytElement ]

Udskrift af lister i liste: liste = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]

print "Elementerne i listen:" for i in liste: for element in i: print element, print

Kørselsresultat: python row.py Elementerne i listen: 1 2 3 4 5 6 7 8 9

>>> liste = range(11) >>> liste [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Lister kan flettes (indeholde andre lister) f.eks: >>> liste = [[]] >>> liste [[]] >>> liste * 3 [[], [], []]

>>> liste_1 = [2, 3] >>> liste_2 = [1,liste_1, 4] >>> len(liste_2) 3 >>> liste_2[1] [2, 3] >>> liste_2[1][0] 2 >>> liste_2[1].append('ekstrapost') >>> liste_2 [1, [2, 3, 'ekstrapost'], 4] >>> liste_1 [2, 3, 'ekstrapost'] >>>

>>> stack = [3, 4, 5] >>> stack.append(6) >>> stack.append(7) >>> stack [3, 4, 5, 6, 7] >>> stack.pop() 7 >>> stack [3, 4, 5, 6] >>> stack.pop() 6 >>> stack.pop() 5 >>> stack [3, 4]

>>> liste = ["Ugleenge","Sæne","Bækkely","Stampen"] >>> for i, v in enumerate(liste): ... print i,v ... 0 Ugleenge 1 Sæne 2 Bækkely 3 Stampen >>>

Der kan også dannes løkke over to eller flere samtidige sekvenser: >>> person = ['Ole', '120', 'naturen'] >>> svar = ['navn:', 'alder:', 'hobby:'] >>> for i, j in zip(person,svar): ... print j,i ... navn: Ole alder: 120 hobby: naturen >>>

Lister kan sammenlignes:
>>> [1, 2, 3] < [1, 2, 4]
True
>>>
>>> [1, 2, 3, 4] < [1, 2, 4]
True
>>>
>>> [2,3,4] <> [2.0,3.0,4.0]
True
>>>
>>> [1, 2] < [1, 2, -1]
True
>>>
>>> [1, 2, 3] == [1.0, 2.0, 3.0]
True
>>>
>>> [1, 2, 3,4] <>[1, 2, 3,"p"]
True
>>>
>>> [1, 2, ['aa', 'ab']] < [1, 2, ['abc', 'a'], 4]

Lister anvendt som stakke

I computersproget FORTH benyttes begrebet stakke meget. Der sammenligner man normalt en stak med en stabel tallerkener. I en sådan stabel tallerkener, vil den nederste under normale forhold blive placeret i bunden at stakken eller stabelen. I FORTH arbejder man normalt med begreberne LIFO (last in first out eller på dansk først ind (altså øverst i tallerkenstabelen) first out eller først ud betyder, som ordet siger først ud - altså at man tager den øverste tallerken (det øverste eller sidst placerede element først. Modsvarende LIFO bruger man også FIFO i FORTH. Forkortelsen FIFO står for first in first out eller på dansk først ind først ud. Overført til tallerkenstablen betyder det, at den nederste tallerken i stakken, er den tjeneren benytter først. Jeg har vagt at forklare princippet ud fra FORTH, fordi det derved også bliver lettere at forstå, hvordan man i Python kan lave noget tilsvarende. I Python kalder man en stak for en queue ligesom normalt må nøjes med at udskrive selve FIFO og LIFO elementerne. Det kan gøres således:

>>> queue = ["Arnager","Dueodde","Nexø","Svaneke"]
>>> queue.pop(0)
'Arnager'
>>> queue.pop(2)
'Svaneke'
>>> queue.append("Gudhjem")
>>> queue.pop(2)
'Gudhjem'
>>> queue.append("Tejn")
>>> queue.pop(2)
'Tejn'
>>>

2.16.1. Funktionelle programmeringsværktøjer

I Python er der tre fordefinerede funktioner, der er meget nyttige i forbindelse med lister:

filter(), map(), and reduce().
Eksempel: Syntaks: filter(funktion,sekvens) returnerer om muligt en sekvens af samme type som den i filters parameterliste. Den returnerede sekvens består af de værdier, der gør, at funktion(argument) er sand (true).

Eksempel:

Beregn Primtal:
Syntaks: filter(funktion, blok)
>>> def f(x): return x % 2 != 0 and x % 3 != 0
...
>>> filter(f, range(2, 25))
[5, 7, 11, 13, 17, 19, 23]

Syntaks: map(funktion, blok)

kalder funktion(parameter) for hver enkelt af sekvensens elementer og returnerer en liste indeholdende returværdierne.

Eksempel: Beregn kubiktal: >>> def kubik(x): return x*x*x ... >>> map(kubik, range(1, 11)) [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000] >>>

map kan også tage flere sekvenser. >>> def kvadrat(x): return x*x ... >>> map(None, sekvens, map(kvadrat, sekvens)) [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25), (6, 36), (7, 49)] >>>

Eksempel: Syntaks: reduce(funktion, sekvens) >>> 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 55 >>>

>>> def sumTotal(x,y): return x + y ... >>> reduce(sumTotal, range(1, 11)) 55 >>>

>>> reduce(sumTotal, range(11) ... ) 55 >>>

Nyhed i Python version 2.3: >>> navne = ['London','Paris','New Yorkbyer','Gudhjem'] >>> [byer.strip() for byer in navne] ['London', 'Paris', 'New Yorkbyer', 'Gudhjem'] >>>

>>> drenge = ["Ole","Per","Sofus","Nikolai"] >>> [navne.strip() for navne in drenge] ['Ole', 'Per', 'Sofus', 'Nikolai'] >>>

>>> lige =  [2, 4, 6]
>>> [3*x for x in lige]
[6, 12, 18]
>>>
>>> [3*x for x in lige if x > 3]
[12, 18]
>>>
>>> [3*x for x in lige if x < 2]
[]
>>>
>>> [[x,x**2] for x in lige]
[[2, 4], [4, 16], [6, 36]]
>>>
>>> lige = [2, 4, 6]
>>> blandede = [4, 3, -9]
>>> [x*y for x in lige for y in blandede]
[8, 6, -18, 16, 12, -36, 24, 18, -54]
>>>
>>> [x+y for x in lige for y in blandede]
[6, 5, -7, 8, 7, -5, 10, 9, -3]
>>>
>>> [lige[i] * blandede[i] for i in range(len(lige))]
[8, 12, -54]
>>>
>>> [str(round(355/113.0, i)) for i in range(1,6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']
>>>
>>> [x**3 for x in range(5)]
[0, 1, 8, 27, 64]
>>>

Tuples består af et anatal værdier adskille med kommaer. Man siger, at tuples kendes på deres kommaer, mens listen kendes på dens firkantede parenteser. Eks:

>>> t = 1,2,3,4,5
>>> t
(1, 2, 3, 4, 5)
>>>
At de adskillende kommaer virkelig betyder noget ses her:
>>> varsel = "Fare forude!"
>>> len(varsel)
12
>>> varsel = "Fare forude!",
>>> len(varsel)
1
>>>
I det første lilfælde er "Fare forude!" en tekststreng, mens det i det sidste tilfælde er en tuple. Forskellen er ene og alene kommaet.

Tuplen og dens anvendelse oprettet ud fra brugerdata:
t = int( raw_input( "Skriv aktuelt timetal: " ) )
m = int( raw_input( "Skriv aktuelt minuttal: " ) )
s = int( raw_input( "Skriv aktuelt sekundtal: " ) )

ligeNu = t, m, s # opret tuple

print "Tuplens indhold er:", ligeNu

print "Antal sekunder siden midnat", \ ( ligeNu[ 0 ] * 3600 + ligeNu[ 1 ] * 60 + ligeNu[ 2 ] )

Kørselsresultat: ajbo@linux:~> python anvendt_tuple.py Skriv aktuelt timetal: 11 Skriv aktuelt minuttal: 17 Skriv aktuelt sekundtal: 13 Tuplens indhold er: (11, 17, 13) Antal sekunder siden midnat 40633

Strengs, listes og tuples anvendelse: strengen = "abcdefghij" tuplen = ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ) listen = [ "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X" ]

print "strengen: ", strengen print "tuplen: ", tuplen print "listen: ", listen

start = int( raw_input( "Vælg startpunkt: " ) ) sidste = int( raw_input( "Vælg slutpunkt: " ) )

print "\nstrengen[", start, ":", sidste, "] = ", \ strengen[ start:sidste ]

print "tuplen[", start, ":", sidste, "] = ", \ tuplen[ start:sidste ]

print "listen[", start, ":", sidste, "] = ", \ listen[ start:sidste ]

Kørselsresultat: strengen: abcdefghij tuplen: (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) listen: ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX', 'X'] Vælg startpunkt: 0 Vælg slutpunkt: 6

strengen[ 0 : 6 ] = abcdef tuplen[ 0 : 6 ] = (1, 2, 3, 4, 5, 6) listen[ 0 : 6 ] = ['I', 'II', 'III', 'IV', 'V', 'VI'] ajbo@linux:~>

Tuples kan flettes (be nested): >>> t = 12345, 54321, 'hej!' >>> t[0] 12345 >>> t (12345, 54321, 'hej!')

>>> # Tuples kan flettes: >>> u = t, (1, 2, 3, 4, 5) >>> u ((12345, 54321, 'hej!'), (1, 2, 3, 4, 5))

Tuples kan sammenlignes: >>> (1, 2, 3) < (1, 2, 4) True >>> >>> (1, 2, 3, 4) < (1, 2, 4) True >>> >>> (2,3,4) <> (2.0,3.0,4.0) False >>> >>> (1, 2) < (1, 2, -1) True >>> >>> (1, 2, 3) == (1.0, 2.0, 3.0) True >>> >>> (1, 2, 3,4) <>(1, 2, 3,"p") True >>> >>> (1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4) True >>>

Sammenligning af Lister og tuples
>>> [1, 2, 3] < (1, 2, 4)
True
>>>
>>> [1, 2, 3, 4] < (1, 2, 4)
True
>>>
>>> [2,3,4] <> (2.0,3.0,4.0)
True
>>>
>>> [1, 2] < (1, 2, -1)
>>> True
>>>
[1, 2, 3] == (1.0, 2.0, 3.0)
True
>>>
>>> [1, 2, 3,4] <> (1, 2, 3,"p")
True
>>>
>>> [1, 2, ['aa', 'ab']] < (1, 2, ('abc', 'a'), 4)
True
>>>

ordliste = {} # opretter tom dictionary
print "Ordlisten indhold:", ordliste

postnumre = { "Rønne": 3700, "Allinge": 3770, "Gudhjem": 3780, "Nexø": 3730} print "\nAlle indsatte postnumre:", postnumre

# access og ret eksistenende ordliste print "\nRønne postnummer:", postnumre[ "Rønne" ] postnumre[ "Gudhjem" ] = 3760 print "Gudhjems rigtige postnummer:", postnumre[ "Gudhjem" ]

# tilføj postnummer postnumre[ "Aakirkeby" ] = 3720 print "\nOrdlistens postnumre efter rettelsen:" print postnumre

# slet indgang fra ordlisten del postnumre[ "Allinge" ] print "\nOrdlistens nuværende indhold:" print postnumre

Ordlisten indhold: {}

Alle indsatte postnumre: {'Nexø': 3730, 'Gudhjem': 3780, 'Rønne': 3700, 'Allinge': 3770}

Rønne postnummer: 3700 Gudhjems rigtige postnummer: 3760

Ordlistens postnumre efter rettelsen: {'Nexø': 3730, 'Aakirkeby': 3720, 'Gudhjem': 3760, 'Rønne': 3700, 'Allinge': 3770}

Ordlistens nuværende indhold: {'Nexø': 3730, 'Aakirkeby': 3720, 'Gudhjem': 3760, 'Rønne': 3700}

Her er et eksempel på anvendelse af en ordliste: >>> postnr = {'Nyker': 3700, 'Hasle': 3790} >>> postnr['Gudhjem'] = 3760 >>> postnr {'Hasle': 3790, 'Nyker': 3700, 'Gudhjem': 3760} >>> >>> del postnr["Hasle"] >>> postnr {'Nyker': 3700, 'Gudhjem': 3760} >>> >>> postnr {'Muleby': 3700, 'Nyker': 3700, 'Gudhjem': 3760} >>> >>> postnr.keys() ['Muleby', 'Nyker', 'Gudhjem'] >>> >>> postnr.has_key("Hasle") 0 >>> >>> postnr.has_key("Gudhjem") 1 >>>

Konstruktøren dict() opretter ordlister direkte fra en liste hvis elementer er tuples: >>> liste = [('Muleby', 3700), ('Nyker', 3700), ('Gudhjem', 3760)] >>> dict(liste) {'Nyker': 3700, 'Muleby': 3700, 'Gudhjem': 3760} >>> eller: >>> dict([('Muleby', 3700), ('Nyker', 3700), ('Gudhjem', 3760)]) {'Nyker': 3700, 'Muleby': 3700, 'Gudhjem': 3760} >>>

>>> liste = [] >>> for i in range(6): ... liste.append((str(i), i* i)) ... >>>

>>> liste = [('0', 0), ('1', 1), ('2', 4), ('3', 9), ('4', 16), ('5', 25)] >>> dict(liste) {'1': 1, '0': 0, '3': 9, '2': 4, '5': 25, '4': 16} >>>

Løkke teknikker: >>> t = "Ugleenge","Sæne","Bækkely","Stampen" >>> t ('Ugleenge', 'S\xe6ne', 'B\xe6kkely', 'Stampen') >>>

ordliste = {"Ugleenge" : 1,"Sæne" : 2,"Bækkely" :3,"Stampen" : 4} >>> for i in ordliste.items(): print i ... ('S\xe6ne', 2) ('B\xe6kkely', 3) ('Ugleenge', 1) ('Stampen', 4) >>>

kalender = { 1 : "Januar", 2 : "Februar", 3 : "Marts", 4 : "April", 5 : "Maj", 6 : "Juni", 7 : "Juli", 8 : "August", 9 : "September", 10 : "Oktober", 11 : "November", 12 : "December" }

print "Ordlistens indhold:" print kalender.items()

print "\nOrdlistens indgange er:" print kalender.keys()

print "\nOrdlistens elementer er:" print kalender.values()

print "\nFor løkke henter ordliste elementer:" for indgang in kalender.keys(): print "kalender[", indgang, "] =", kalender[ indgang ]

Kørselsresultat: ajbo@linux:~> python kalender.py Ordlistens indhold: [(1, 'Januar'), (2, 'Februar'), (3, 'Marts'), (4, 'April'), (5, 'Maj'), (6, 'Juni'), (7, 'Juli'), (8, 'August'), (9, 'September'), (10, 'Oktober'), (11, 'November'), (12, 'December')]

Ordlistens indeks (indgange) er: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

Ordlistens elementer er: ['Januar', 'Februar', 'Marts', 'April', 'Maj', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'December']

For løkke henter ordliste elementer: kalender[ 1 ] = Januar kalender[ 2 ] = Februar kalender[ 3 ] = Marts kalender[ 4 ] = April kalender[ 5 ] = Maj kalender[ 6 ] = Juni kalender[ 7 ] = Juli kalender[ 8 ] = August kalender[ 9 ] = September kalender[ 10 ] = Oktober kalender[ 11 ] = November kalender[ 12 ] = December ajbo@linux:~>