Python Dictionary KeyError

Rivi 16, on OK, mutta rivillä 15 virhe, mutta mikä? Halusin sen tulostavan “Maanantai”, eikä Erroria.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# V I I K O N P Ä I V Ä T . P Y

Viikonpäivät={
	'Maanantai':	1,
	'Tiistai':	2,
	'Keskiviikko':	3,
	'Torstai':	4,
	'Perjantai':	5,
	'Lauantai':	6,
	'Sunnuntai':	7
}

print( "Viikon ensimmäinen päivä on: ", Viikonpäivät[1] )
print( "Tiistai on numeroltaan: ", Viikonpäivät['Tiistai'] )



Tässä vielä tuo koodi, joka olisi pitänyt liittää tuohon kysymykseen jo alun alkaen.

Sitkeän hakemisen tuloksena löysin tällaisen ratkaisun:

print( list(Viikonpäivät.keys())[0])

Tuossahan dictionary listan sisältö sijoitetaan normaalin listan arvoksi, ja sitten siltä listalta tulostetaan nolla indeksin omaava avaimen arvo.

Kyllä on hankalaa tulostaa tietty yksittäisen avaimen arvo dictionary listalta, HUH huh.

No, ehkä oli väärin sanottu, että “dictionary listan sisältö sijoitetaan normaalin listan arvoksi”, koska eihän tuossa koko dictionary listan sisältöä sijoiteta, vaan ainoastaan avaimet. Ja näin se menisi kun vastaava tehdään avainten arvoille:

print( list(Viikonpäivät.values())[0])

Dictionary lista, min() ja max() Funktiot

Päänvaivaa saattaa myös tuottaa min() ja max() funktioiden soveltaminenkin. Tässä pari esimerkkiä, ihan vain ajan kuluksi tehtynä. Ainakin tuo merkkijonon pituutta koskeva esimerkki on niin hakusessa, että joku saattaa sen puolituntia säästää kun tähän törmää.


Dictionary listan AVAIN ja ARVO merkkijonoja

List = {'10':"Aamu", '222':"Ilta", '333':"Yö"}

Tulostetaan merkkijonoltaan lyhyin avain (‘10’) ja avaimenarvo (‘Yö’)

print( min(list(List.values()), key=len ) )  #Yö
print( min( list( List.keys() ), key=len ) ) #10


Dictionary listan AVAIN ja ARVO kokonaislukuja

List = { 10:33, 222:23, 333:-4 }

Tulostetaan arvoltaan pienin avain (‘10’) ja avaimenarvo (’-4’)

print( min(List.values()) )  #-4
print( min(List.keys()) )  #10

Minusta näyttää, että käytät dict-tyyppiä väärin päin. Sinulla on avaimina viikonpäivät ja arvoina niiden järjestysnumerot. Tuollaisella dict:llä voit hakea järjestysnumeron tietämällä viikonpäivän:
Viikonpäivät['Maanantai'] == 1

Näin päin saat numerolla viikonpäivän nimen:
Viikonpäivät = {
1: ‘maanantai’,
2: ‘tiistai’,
3: ‘keskiviikko’,
4: ‘torstai’,
5: ‘perjantai’,
6: ‘lauantai’,
7: ‘sunnuntai’,
]

Toisaalta jos tuossa on tarkoitus säityttää vain viikonpäivien nimiä indeksoituina numeroilla, niin olisi järkevämpää käyttää listaa:
Viikonpäivät = ["maanantai", "tiistai", "keskiviikko", "torstai", "perjantai", "lauantai", "sunnuntai"]
Toki tuo indeksoidaan nollasta alkaen, mutta voihan sille kirjoittaa metodin, jolla sen hakee, jos ero on tärkeä. Tai säilyttää ensimmäisessä alkiossa, vaikka None-arvoa. Tai jos välttämättä haluaa, niin voi tehdä list-tyypin aliluokan tai muun oman säilötyypin ja käyttää sitä indeksointia kuin haluaa.

1 tykkäys

Juuri noin. Vaikka dict -tyyppinen arvotaulukko tuntuukin äkisti mielekkäältä ratkaisulta moneen tarpeeseen, ei se kuitenkaan tunnu sitä olevan.

Kun ajattelee että on “Matti” ja matilla “puhelinnumero”, on helppo hakea uniikilla avaimella Matin puhelinnumero, mutta kun halutaankin selvittää, kenen numero joku on, asiat mutkistuu pahasti. Halusin kyseenalaistaa koko arvotaulukko tyypin olemassa olon, koska olemassa olevat tuple- ja lista-tyyppiset arvoluettelot hoitavat saman asian paremmin.

Tämän ymmärtämiseksi pitää vähän oppia tietojenkäsittelytiedettä. Pythonin dict on kuvaus (map), jossa voi käyttää melkein mielivaltaista avainta. Pythonin list taas on taulukko (array), jonka indeksointi alkaa aina nollasta ja kasvaa siitä suuremmaksi, mutta kuvauksessa avainten ei tarvitse täyttää jokaista arvoa ja indeksoida voi haluamallaan tyypillä. Siihen voi vaikka kirjoittaa oman luokan, jonka olioita sitten käyttää.

1 tykkäys

Miksi tämä on niin korvaamaton?

Dictin kaltainen tietorakenne (rakkaalla lapsella on monta nimeä, mm. map ja hash) on aika monikäyttöinen. Sinun sovelluksessai se ei ehkä pääse erityisesti oikeuksiinsa, mutta se tulee usein vastaan erilaisissa yhteyksissä:

  • Web-sovelluksen palvelinohjelmistossa http-otsikkotiedot (headers) ovat usein dictissä, sillä niiden nimillä ja sisällöillä ei ole mitään taattua formaattia, jotta ne voisivat olla vaikkapa jonkin luokan aina tietyissä kentissä.
  • Jos teet sovelluksen, joka lukee tiedostojärjestelmästä tai verkosta joukon tiedostoja tarpeen mukaan, dict voisi sopia yksinkertaiseksi välimuistitoteutukseksi. Avaimina voisi silloin olla tiedostojen polkuja ja arvoina joko tiedostojen sisältö raakana puskurina tai kenties jollain tavalla tulkattuna, sovelluksesta riippuen.
1 tykkäys

Joo, kaipa se on paikkansa lunastanut, kun mukaan on otettu. :smile:
Huomasin myös että täällä on myös Syntax highlighting tuki python koodille, siispä testataanpas säilyykö sisennykset niin että esimerkit toimii suoraan kopioituna preparoimatta:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# C O L O R E D   H I N N A S T O . P Y

from termcolor import colored, cprint

Hinnasto={
'Pulla':'2,45€',
'Kahvi':'1,60€',
'Tee'  :'0,80€',
'Puuro':'1,80€',
}


cprint('\n  TUOTE\tHINTA','green',attrs=['bold'])
for avain, arvo in Hinnasto.items():
	t1 = colored('  ' + avain, 'red', attrs=['bold'])
	t2 = colored('\t' + arvo, 'blue', attrs=['bold'])
	print(t1 + t2)

Aloittelijan on vaikea palauttaa hajonneet sisennykset, koska sen tekeminen edellyttää jo perusasioiden tuntemusta. Hieno asia, vaikkei toimisikaan, on paljon fiksumman näköinen, kuin pelkkänä <pre> </pre> tageilla esitettynä, joilla sen edellisellä kerralla sain pysymään kasassa.