← Python/Verzamelen en veranderen
Les 7 van 8
MODULE 04 · 07◷ 28 min

Werk veilig met geneste gegevens

Na deze les kun je
  • Rijen en velden gericht uitlezen
  • Nieuwe binnenste lijsten maken
  • Gegevens filteren en totaliseren

Een zaalindeling bevat rijen met stoelen, terwijl een deelnemersoverzicht per groep meerdere velden heeft. Je hebt dan meer nodig dan één vlakke lijst. Door bekende collecties te combineren kun je zulke gegevens bewaren, lezen en gericht kopiëren.

Eerst de buitenkant, dan de binnenkant

Bij geneste gegevens bevat een collectie weer andere collecties. Een tabel kan bijvoorbeeld een lijst met rijlijsten zijn. grid[row][column] kiest eerst een rij uit de buitenste lijst en daarna een element uit die rij.

Met grid[1][0] lees je daarom het eerste element van de tweede rij. Beide indexen beginnen bij nul, maar ze hebben verschillende betekenissen. De opdrachten geven geldige indexen; zelf ongeldige posities afvangen hoort hier nog niet bij.

Druk op Voorbeeld uitvoeren. De eerste regels lezen een positie, tellen iedere rij op en maken vervolgens een versie waarvan de rijen apart gewijzigd kunnen worden.

Tabelposities, eigen rijen en bevestigde groepen
grid = [[2, 5, 0], [1, 4, 3]]
print(grid[1][0])
print([sum(row) for row in grid])
copy = [row[:] for row in grid]
copy[0][1] = 9
print(grid[0])
print(copy[0])
groups = [
    {"adults": 2, "children": 1, "confirmed": True},
    {"adults": 8, "children": 4, "confirmed": False},
]
people = 0
for group in groups:
    if group["confirmed"]:
        people += group["adults"] + group["children"]
print(people)
Verwachte uitvoer
1
[7, 8]
[2, 5, 0]
[2, 9, 0]
3
RijindexKolom 0Kolom 1Kolom 2Som
02507
11438

De functie sum telt de getallen in een reeks op. Voor een lege rij geeft zij nul. Door voor iedere rij een som te verzamelen krijg je een lijst met rijtotalen, niet één getal voor de hele tabel.

De buitenste volgorde blijft daarbij betekenisvol. Het eerste totaal hoort bij de eerste rij, ook wanneer die rij leeg is. Sla zo'n rij niet stilzwijgend over: dan verschuiven de totalen ten opzichte van hun bron.

Kopieer ook de rijen die je wilt veranderen

Uit de sliceles weet je dat grid[:] alleen de buitenste lijst kopieert. De rijlijsten blijven dan gedeeld. Wil je een rij aanpassen zonder terugwerking, maak dan ook voor iedere rij een nieuwe lijst.

Een comprehension kan dat doen: doorloop de rijen en neem van iedere rij een slice. Het voorbeeld vervangt daarna een getal in de nieuwe eerste rij. De oorspronkelijke vijf blijft in de oude tabel staan.

grid   ──► lijst A ──► rij A: 2, 5, 0
copy   ──► lijst B ──► rij B: 2, 9, 0

Beide pijlen eindigen nu bij verschillende rijobjecten. De rij bevat hier alleen getallen, zodat dit ene extra kopieerniveau voldoende is. Dit is geen algemene diepe kopie van willekeurig veel geneste objecten.

Veelgemaakte fout: de indexen verwisselen

De twee indexen hebben hetzelfde type, maar zijn niet uitwisselbaar. In deze zelfstandige foutvariant worden rij en kolom omgedraaid. Beide gekozen posities bestaan, dus Python geeft geen foutmelding.

Geldige indexen met de verkeerde betekenis
grid = [[2, 5, 0], [1, 4, 3]]
row = 1
column = 0
print(grid[column][row])
print(grid[row][column])
Verwachte uitvoer
5
1

Het antwoord is vijf in plaats van één. De code heeft kolom nul als rijindex gebruikt en rij één als kolomindex. Een getal zonder foutmelding is dus niet vanzelf het juiste getal.

Volg beide stappen bij het lezen: welke rij krijg je eerst, en welke kolom lees je daaruit? Gebruik bij een test een tabel met verschillende waarden buiten de diagonaal. Dan valt een verwisseling beter op dan bij een symmetrische tabel.

Lijsten met betekenisvolle velden

Een record is hier een dictionary met afgesproken velden voor één ding. De laatste helft van het werkende voorbeeld gebruikt groepsrecords met volwassenen, kinderen en een bevestigingsveld. De buitenste lijst bewaart meerdere van zulke groepen.

De lus kiest telkens één groep. De voorwaarde leest confirmed; alleen bij True worden de twee aantallen aan het totaal toegevoegd. De grote onbevestigde groep telt daardoor niet mee.

In de opdrachten gebruik je hetzelfde patroon voor actieve producten. Lees price, count en active op naam en tel alleen het product van prijs en aantal van actieve records op. De velden bestaan en hebben de afgesproken typen; een lege invoer of uitsluitend inactieve producten geeft nul.

AAN DE SLAG 0/4
1

Kies eerst de rij

Laat cell eerst row en daarna column gebruiken.

2

Bewaar één totaal per rij

Laat totals iedere rij optellen en de rijvolgorde behouden.

3

Maak onafhankelijke rijen

Laat copy_rows ook iedere binnenste rij kopiëren.

4

Filter vóór het optellen

Laat total_available alleen price maal count van actieve producten optellen.

Wat je meeneemt

  • Bij twee indexen kies je eerst de rij en daarna de kolom.
  • Een onafhankelijke tabelkopie heeft ook nieuwe rijen nodig wanneer je die rijen wilt wijzigen.
  • Lees bij records de velden op naam en filter vóór je de waarden bij een totaal optelt.

Hierna combineer je lijsten en records in een takenlijst met duidelijke wijzigingsafspraken.

main.py
UitvoerPython
›
›_

Hier komt je resultaat.

Voer je code uit en ontdek
wat je hebt gemaakt.

0/4 stappen
EVEN MEEKIJKEN

Bekijk hoe het kan.

Je mag de oplossing bekijken. Deze poging telt dan niet mee als afgeronde les. Met Reset kun je daarna opnieuw zelf oefenen.