← Python/Idiomatisch en performance
Les 2 van 8
MODULE 13 · 02◷ 30 min

Een sortering uitleggen met een sleutel

Na deze les kun je
  • Een nieuwe gesorteerde lijst van sorteren ter plaatse onderscheiden.
  • Een sleutel met casefold of meerdere onderdelen kiezen.
  • Stabiele volgorde en één sleutelberekening per element waarnemen.

Een planning is op invoervolgorde gemakkelijk bij te werken, maar de medewerker wil eerst urgente korte klussen zien. Je wilt die volgorde kunnen uitleggen zonder een ondoorzichtige reeks vergelijkingen te schrijven. Een sorteersleutel maakt de keuze per element zichtbaar.

Een nieuwe lijst of dezelfde lijst

sorted neemt een iterable en geeft een nieuwe lijst terug. De ontvangen lijst houdt haar volgorde. Gebruik dat wanneer meerdere onderdelen van je programma dezelfde invoer gebruiken en ieder een eigen weergave nodig heeft.

De methode list.sort verandert juist die lijst zelf en geeft None terug. Een tweede naam voor dezelfde lijst ziet die verandering ook. De keuze tussen deze vormen is dus een keuze over mutatie, niet alleen over schrijfstijl.

Een vergelijkbare sleutel kiezen

Een sleutel is de waarde waarop je wilt ordenen. Met key=str.casefold krijgt iedere naam een tekstvorm voor een vergelijking die hoofdletters minder bepalend maakt. De oorspronkelijke namen blijven in het resultaat staan; de sleutel vervangt ze niet.

Unicode maakt dit verschil concreet: casefold geeft zowel ß als SS de sleutel ss. Lower maakt die twee sleutels niet gelijk. Bij casefold blijft daarom ook tussen deze twee oorspronkelijke strings de bronvolgorde behouden.

Python sorteert stabiel. Als twee sleutels gelijk zijn, houden die elementen hun onderlinge bronvolgorde. Bij "Bo" en "bo" ontstaat dezelfde casefold-sleutel, maar je schrijft beide namen niet stilzwijgend om naar kleine letters.

Sorteersleutels veranderen de oorspronkelijke namen niet
visitors = ["zoe", "Bo", "ada", "bo"]
ordered = sorted(visitors, key=str.casefold)
print(ordered)
print(visitors)
Verwachte uitvoer
['ada', 'Bo', 'bo', 'zoe']
['zoe', 'Bo', 'ada', 'bo']

Het voorbeeld bewaart de invoerlijst en toont daarnaast een nieuwe weergave. Je ziet ook twee namen met dezelfde sleutel in hun oorspronkelijke onderlinge volgorde. Stabiliteit kan bijvoorbeeld eerdere handmatige keuzes behouden.

Meerdere afspraken in één tuple

Een tuple wordt van links naar rechts vergeleken. Voor taken met (priority, minutes, label) kun je (-priority, minutes) als sleutel teruggeven. Het minteken zet de hoogste numerieke prioriteit vooraan, terwijl de duur binnen die groep oplopend blijft.

reverse=True op een hele tuplesleutel keert alle vergelijkingsonderdelen om. Dat zou ook lange taken vóór korte zetten. Een expliciete sleutel beschrijft beter welke richting per onderdeel bedoeld is.

Bij volledig gelijke sleutels blijft de bronvolgorde behouden. Voeg daarom niet automatisch het etiket als derde sleutel toe: dat zou een nieuwe afspraak introduceren. De opdracht bepaalt welke onderdelen tellen.

Veelgemaakte fout: het resultaat verdwijnt

Je schrijft ordered = names.sort() en verwacht een nieuwe lijst. ordered bevat dan None, terwijl names al veranderd is. Een latere lus over ordered kan daardoor een TypeError geven.

De mutatie en de retourwaarde apart bekijken
colors = ["rood", "blauw", "groen"]
alias = colors
returned = colors.sort()
print(returned)
print(alias)
print(alias is colors)
Verwachte uitvoer
None
['blauw', 'groen', 'rood']
True

De twee namen in dit voorbeeld verwijzen naar hetzelfde lijstobject. De teruggegeven waarde en de gemuteerde lijst zijn afzonderlijke waarnemingen. Kijk steeds naar beide voordat je een sorteerfunctie kiest.

Sleutels berekenen kost ook werk

De key-functie wordt bij een sortering eenmaal per invoerelement aangeroepen. Dat is prettig als een sleutel wat rekenwerk vraagt. Een comparator die bij iedere vergelijking opnieuw zoekt of rekent, kan die bewerking veel vaker uitvoeren.

De vierde oefening ontvangt een gewone, zuivere scorefunctie. Geef haar als key door en bewaar de oorspronkelijke elementen. Roep haar niet daarnaast nog eens aan voor logging of een overbodige voorcontrole; de meegeleverde waarnemer telt echte aanroepen.

AAN DE SLAG 0/4
1

Namen in een nieuwe weergave

Vul alphabetical(names) in: geef een nieuwe lijst met de oorspronkelijke strings, gesorteerd op str.casefold. Behoud bij gelijke sleutels hun invoervolgorde en wijzig de bron niet.

2

Urgent en daarna kort

Vul rank_jobs(jobs) in: iedere taak is (priority, minutes, label). Geef een nieuwe lijst met eerst de hoogste prioriteit, daarna de kleinste duur; bij gelijke prioriteit en duur geldt de bronvolgorde. Wijzig de bron niet.

3

Bewust dezelfde lijst aanpassen

Vul reorder_in_place(names) in: sorteer de ontvangen lijst zelf op str.casefold met stabiele volgorde en geef None terug. Andere verwijzingen moeten dezelfde gewijzigde lijst zien.

4

Een berekening als key doorgeven

Vul by_score(items, score) in: geef een nieuwe stabiel oplopend gesorteerde lijst volgens score(item). Bereken de score precies eenmaal per element en wijzig de bron niet.

Samenvatting

  • sorted maakt een nieuwe lijst; sort wijzigt de bestaande en geeft None.
  • Een sleutel vertelt welke eigenschappen de volgorde bepalen.
  • Stabiliteit behoudt de volgorde van elementen met gelijke sleutels.

In de volgende les verwerk je gegevens lui en bepaal je hoeveel invoer je werkelijk nodig hebt.

sorting_tools.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.