Osa 5

Lexikon

Listor kan vara händiga i flera situationer, men deras svaga punkt är att elementen hämtas med hjälp av index (0, 1, 2 o.s.v.). Om du vill hitta ett element i en lista måste du alltså veta dess index, eller alternativt gå igenom hela listan.

En ytterligare central datastruktur i Python är lexikon, eller ordlistor (eng. dictionary). I lexikon är elementen indexerade med hjälp av nycklar, där varje nyckel har ett värde. Värden som lagrats i ett lexikon kan hämtas och ändras med hjälp av dess nyckel.

Att använda lexikon

Det följande visar hur datastrukturen fungerar. Här är ett enkelt lexikon som innehåller översättningar från finska till svenska:

lexikon = {}

lexikon["apina"] = "apa"
lexikon["banaani"] = "banan"
lexikon["cembalo"] = "cembalo"

print(len(lexikon))
print(lexikon)
print(lexikon["apina"])
Exempelutskrift

3 {'apina': 'apa', 'banaani': 'banan', 'cembalo': 'cembalo'} apa

Notationen {} skapar ett tomt lexikon där vi kan lägga till element. Tre nyckel-värdepar skapas: "apina" är knutet till "apa", "banaani" till "banan" och "cembalo" till "cembalo". Till slut skriver vi ut antalet nyckel-värdepar i lexikonet, lexikonets innehåll samt det värde som tillhör nyckeln "apina".

Efter att vi har skapat ett lexikon kan vi också använda det med indata från användaren:

ord = input("Ange ord: ")
if ord in lexikon:
    print("Översättning:", lexikon[ord])
else:
    print("Ordet hittades inte")

Lägg märke till hur vi använder in-operatorn ovan. När vi använder operatorn för variabler med typen lexikon, kollar operatorn om den första operanden finns bland lexikonets nycklar. Så här kan det se ut när programmet körs:

Exempelutskrift

Ange ord: apina Översättning: apa

Exempelutskrift

Ange ord: pöllö Ordet hittades inte

Vad kan lagras i ett lexikon?

Datatypen kallas lexikon, men det innebär inte att man bara skulle kunna lagra strängar där. I det här exemplet är nycklarna strängar men värdena är heltal:

resultat = {}
resultat["Maja"] = 4
resultat["Lisa"] = 5
resultat["Kalle"] = 2

Här är nycklarna heltal medan värdena är listor:

listor = {}
listor[5] = [1, 2, 3]
listor[42] = [5, 4, 5, 4, 5]
listor[100] = [5, 2, 3]

Hur nycklar och värden fungerar

Varje nyckel kan endast förekomma en gång i ett lexikon. Om du lägger till ett nytt värde med en nyckel som redan finns i lexikonet, kommer det ursprungliga värdet kopplat till nyckeln att ersättas med det nya värdet:

lexikon["suuri"] = "väldig"
lexikon["suuri"] = "stor"
print(lexikon["suuri"])
Exempelutskrift

stor

Alla nycklar i ett lexikon måste vara oföränderliga. Det betyder att en lista inte kan vara en nyckel, eftersom vi kan ändra på en lista. Den här koden ger till exempel ett fel:

lexikon[[1, 2, 3]] = 5
Exempelutskrift

TypeError: unhashable type: 'list'

Till skillnad från nycklar, kan värdena i ett lexikon ändra. Därmed kan vilken som helst typ av data lagras som värden. Ett och samma värde kan också vara kopplat till flera nycklar i samma lexikon.

Loading
Loading

Gå igenom ett lexikon

Den bekanta for element in samling -loopen kan också användas för att gå igenom ett lexikon. Som standard går loopen då igenom lexikonets nycklar. I följande exempel skrivs varje nyckel och respektive värde:

lexikon = {}

lexikon["apina"] = "apa"
lexikon["banaani"] = "banan"
lexikon["cembalo"] = "cembalo"

for nyckel in lexikon:
    print("nyckel:", nyckel)
    print("värde:", lexikon[nyckel])
Exempelutskrift

nyckel: apina värde: apa nyckel: banaani värde: banan nyckel: cembalo värde: cembalo

Ibland behöver du i stället gå igenom lexikonets innehåll, inte endast nycklarna. Då kan du använda metoden items som returnerar alla nycklar och värden, ett par i sänder:

for nyckel, varde in lexikon.items():
    print("nyckel:", nyckel)
    print("värde:", varde)

I exemplen ovan märkte du kanske att nycklar behandlas i den ordning som de lagts till i lexikonet. Eftersom nycklarna behandlas enligt sina hashvärden, borde ordningen inte ha någon skillnad i programmen. I flera äldre versioner av Python är det dessutom inte garanterat att ordningen är den samma som nycklarna lagts till.

Några mer avancerade sätt att använda lexikon

Låt oss se på en lista med ord:

ordlista = [
  "banan", "mjölk", "ost", "jordnöt", "pasta", "mjöl", "majs",
  "tomat", "korv", "vitlök", "margarin", "jordnöt", "majs",
  "ost", "pasta", "pasta", "vitlök", "ost", "socker"
]

Vi skulle vilja analysera den här ordlistan på olika sätt. Vi är till exempel intresserade av hur många gånger de olika orden förekommer i listan.

Ett lexikon fungerar bra för att hålla reda på den typen av information. I exemplet nedan går vi igenom orden i listan. Vi använder sedan orden som nycklar i ett nytt lexikon, så att värdet som är kopplat till varje nyckel indikerar hur många gånger det specifika ordet har förekommit:

def antal(lista):
    ordsamling = {}
    for ord in lista:
        # om ordet inte förekommit ska nyckeln skapas och få ett värde
        if ord not in ordsamling:
            ordsamling[ord] = 0
        # öka på antalet gånger ordet förekommit
        ordsamling[ord] += 1
    return ordsamling

# vi anropar funktionen
print(antal(ordlista))

Programmet skriver ut det följande:

Exempelutskrift

{'banan': 1, 'mjölk': 1, 'ost': 3, 'jordnöt': 2, 'pasta': 3, 'mjöl': 1, 'majs': 2, 'tomat': 1, 'korv': 1, 'vitlök': 2, 'margarin': 1, 'socker': 1}

Hur skulle vi kunna sortera orden enligt den första bokstaven i varje ord? Även för det kan vi använda ett lexikon:

def enligt_forsta_bokstaven(lista):
    grupper = {}
    for ord in lista:
        forsta_bokstaven = ord[0]
        # skapa en lista då bokstaven förekommer för den första gången
        if forsta_bokstaven not in grupper:
            grupper[forsta_bokstaven] = []
        # lägg till ordet under den korrekta bokstaven
        grupper[forsta_bokstaven].append(ord)
    return grupper

grupper = enligt_forsta_bokstaven(ordlista)

for nyckel, varde in grupper.items():
    print(f"ord som börjar med {nyckel}: ")
    for ord in varde:
        print(ord)

Funktionens struktur påminner om det tidigare exemplet, men den här gången är värden lagrade i form av listor. Programmet ger följande utskrift:

Exempelutskrift

ord som börjar med b: banan ord som börjar med m: mjölk mjöl majs margarin majs ord som börjar med o: ost ost ost ord som börjar med j: jordnöt jordnöt ord som börjar med p: pasta pasta pasta ord som börjar med t: tomat ord som börjar med k: korv ord som börjar med v: vitlök vitlök ord som börjar med s: socker

Loading
Loading
Loading

Att ta bort nycklar och värden från ett lexikon

Man kan ta bort nyckel-värdepar ur ett lexikon på två sätt. Det första är att använda instruktionen del:

personal = {"Antti": "lektor", "Emilia": "professor", "Arto": "lektor"}
del personal["Arto"]
print(personal)
Exempelutskrift

{'Antti': 'lektor', 'Emilia': 'professor'}

Om du försöker använda del-instruktionen för att ta bort en nyckel som inte finns i listan, kommer ett fel att uppstå:

personal = {"Antti": "lektor", "Emilia": "professor", "Arto": "lektor"}
del personal["Jukka"]
Exempelutskrift
>>> del personal["Jukka"]
Traceback (most recent call last):
  File "", line 1, in 
KeyError: 'Jukka'

Därmed lönar det sig att kolla om en nyckel existerar före du försöker avlägsna den från listan:

personal = {"Antti": "lektor", "Emilia": "professor", "Arto": "lektor"}
if "Jukka" in personal:
  del personal["Jukka"]
  print("Avlägsnades")
else:
  print("Hittade inte personen som skulle avlägsnas")

Ett annat sätt för att ta bort element från listan är att använda metoden pop:

personal = {"Antti": "lektor", "Emilia": "professor", "Arto": "lektor"}
borttagen = personal.pop("Arto")
print(personal)
print("Avlägsnade", borttagen)
Exempelutskrift

{'Antti': 'lektor', 'Emilia': 'professor'} Avlägsnade lektor

Metoden pop returnerar också värdet på elementet som togs bort.

Metoden pop kommer också i vanliga fall att ge ett fel om nyckeln som man försöker ta bort saknas i lexikonet. Det här kan man dock undvika genom att som andra argument till metoden ge ett standardväde som ska returneras i de fall där nyckeln saknas. Värdet None kan till exempel användas här:

personal = {"Antti": "lektor", "Emilia": "professor", "Arto": "lektor"}
borttagen = personal.pop("Jukka", None)
if borttagen == None:
  print("Hittade inte personen som skulle avlägsnas")
else:
  print("Avlägsnade", borttagen)
Exempelutskrift

Hittade inte personen som skulle avlägsnas

Obs! Om du vill tömma ett lexikon och försöker göra det med en for-loop…

personal = {"Antti": "lektor", "Emilia": "professor", "Arto": "lektor"}
for nyckel in personal:
  del personal[nyckel]

…kommer du att få ett felmeddelande:

Exempelutskrift

RuntimeError: dictionary changed size during iteration

Som vi nämnt tidigare kan vi inte göra ändringar i en samling i samband med att vi går igenom den med en for-loop.

Lexikon har dock en inbyggd metod som kan användas istället:

personal.clear()
Loading
Loading

Använda lexikon för att strukturera data

Lexikon fungerar bra för att strukturera data. Följande kodsnutt skapar ett lexikon som innehåller information om en person:

person = {"namn": "Peppa Python", "längd": 154, "vikt": 61, "ålder:" 44}

Här har vi alltså en person som heter Peppa Python. Hennes längd är 154, vikt 61 och ålder 44. Samma information kunde också lagras i skilda variabler:

namn = "Peppa Python"
längd = 154
vikt = 61
alder = 44

Fördelen med lexikon är att det är en samling och kan samla relaterade data under en och samma variabel. Det är dessutom enkelt att komma åt den information man är ute efter. Samma funktionalitet erbjuds också av listor:

person = ["Peppa Python", 153, 61, 44]

Nackdelen med listor är att programmeraren måste komma ihåg eller hålla på vilket index som används för vilken information. Det finns inget som indikerar att person[2] innehåller vikten och person[3] åldern. När man använder lexikon, undviker man det här problemet eftersom all information finns lagrad under namngivna nycklar.

Om vi antar att det finns flera personer som definierats i samma format, kan vi komma åt deras information på följande sätt:

person1 = {"namn": "Peppa Python", "längd": 154, "vikt": 61, "ålder": 44}
person2 = {"namn": "Philip Python", "längd": 174, "vikt": 103, "ålder": 31}
person3 = {"namn": "Pedro Python", "längd": 191, "vikt": 71, "ålder": 14}

personer = [person1, person2, person3]

for person in personer:
    print(person["namn"])

total_langd = 0
for person in personer:
    total_langd += person["längd"]

print("Medellängden är", total_langd / len(personer))
Exempelutskrift

Peppa Python Philip Python Pedro Python Medellängden är 173.0

Loading
Loading
Loading...
:
Loading...

Log in to view the quiz

Du har nått slutet av den här delen! Fortsätt till nästa del:

Se dina poäng genom att klicka på cirkeln nere till höger av sidan.