← Python/Tekst begrijpen en verwerken
Les 5 van 8
MODULE 05 · 05◷ 28 min

Vergelijk tekst in een gezamenlijke Unicode-vorm

Na deze les kun je
  • Codepunten van zichtbare tekens onderscheiden
  • NFC met unicodedata gebruiken
  • Normalisatie onderscheiden van hoofdletters en compatibiliteitsvervanging

Twee namen zien er hetzelfde uit, maar je programma beschouwt ze als verschillend. Dat kan gebeuren wanneer een letter met accent op twee manieren is opgebouwd. Je onderzoekt daarom de codepunten achter de zichtbare tekst voordat je een vergelijking maakt.

Eén uiterlijk, meer dan één opbouw

Een string bestaat uit Unicode-codepunten. De letter ë kan één codepunt zijn, maar ook een gewone e gevolgd door een los trema. Het scherm kan beide combinaties hetzelfde tekenen, terwijl hun reeksen codepunten verschillen.

Daarom telt len niet altijd het aantal zichtbare letters. Ook indexeren en slicen werken met codepunten. Een slice kan dus een los accent van zijn basisletter scheiden; tekst bewerken vraagt soms meer dan alleen een positie kiezen.

OpbouwAantal codepuntenUiterlijk
Eén voorgevormde letter ë1ë
De letter e plus een los trema2ë

De schrijfwijze \u0308 in een Python-string kiest het codepunt van het losse trema. Die zes broncodetekens worden bij het lezen van de string één codepunt. Het is dezelfde soort scheiding tussen broncode en tekstwaarde die je van \n kent.

Een gezamenlijke vorm kiezen

Normalisatie zet zulke gelijkwaardige opbouwen om naar een afgesproken vorm. In deze les kiezen we NFC, een vorm die waar mogelijk bij elkaar horende onderdelen samenstelt. Je vergelijkt daarna de twee genormaliseerde strings.

Daarvoor gebruiken we unicodedata, een module uit de standaardbibliotheek: een verzameling beschikbare functies. Met import unicodedata maak je haar naam beschikbaar. Daarna roept unicodedata.normalize("NFC", text) de normalisatiefunctie aan.

Voorspel eerst de vergelijking en de twee lengtes in het zelfstandige voorbeeld. Voer het daarna uit en kijk wat er verandert wanneer beide namen dezelfde vorm krijgen.

Twee opbouwen van een naam
import unicodedata

left = "Zoe\u0308"
right = "Zoë"
print(left == right)
print(len(left), len(right))
print(unicodedata.normalize("NFC", left))
print(unicodedata.normalize("NFC", left) == right)
Verwachte uitvoer
False
4 3
Zoë
True

Je oorspronkelijke variabelen blijven bestaan zoals ze waren. De functie geeft een tekstwaarde terug; je moet die gebruiken of bewaren. Alleen de functie aanroepen zonder haar resultaat te gebruiken verandert de oorspronkelijke string niet.

Veelgemaakte fout: alleen kleine letters maken

Hoofdletters aanpassen is een andere bewerking dan codepunten normaliseren. In de volgende foutvariant zijn beide namen al in kleine letters, maar heeft één naam nog een los accent.

Kleine letters lossen de opbouw niet op
name = "cafe\u0301"
print(name.lower() == "café")
Verwachte uitvoer
False

De vergelijking blijft onwaar. lower heeft geen reden om dat losse accent met de voorafgaande letter samen te stellen. Normaliseer beide kanten wanneer jouw afspraak een vergelijking in NFC vraagt.

Gelijkwaardig is niet hetzelfde als gelijk ogend

NFC maakt niet alle tekens die op elkaar lijken hetzelfde. Een gewone hoofdletter A en een brede variant blijven verschillende tekens. Ook een ligatuur of omcirkeld cijfer wordt niet zomaar gewone tekst.

Er bestaan andere vormen, waaronder NFKC, die zulke compatibiliteitsvarianten wel kunnen vervangen. Dat is hier niet het contract: je moet de aangeleverde betekenis en schrijfwijze zo veel mogelijk behouden. Gebruik daarom precies NFC.

De opdrachten veranderen hoofdletters en spaties niet. same_text vergelijkt de NFC-vorm van beide invoeren, dus een verschillende hoofdletter blijft een verschil. Een lege string is ook gewoon een geldige tekstwaarde.

AAN DE SLAG 0/4
1

Kies de NFC-vorm

Laat normalise de NFC-vorm van de tekst teruggeven. Stel losse accenten waar mogelijk samen en behoud al genormaliseerde tekst.

2

Behoud compatibiliteitsvarianten

Laat normalise de NFC-afspraak volgen: vervang een brede letter, ligatuur of omcirkeld cijfer niet door gewone tekens.

3

Vergelijk beide genormaliseerde waarden

Laat same_text een boolean teruggeven die de NFC-vorm van beide teksten vergelijkt. Hoofdletters blijven betekenisvol.

4

Behoud spaties en hoofdletters

Laat normalise alleen de NFC-bewerking doen. Verwijder geen witruimte en verander geen hoofdletters; lege tekst blijft geldig.

Wat je meeneemt

  • Zichtbare tekens en Unicode-codepunten zijn niet altijd één op één verbonden.
  • NFC geeft gelijkwaardige opbouwen een gezamenlijke vorm voor vergelijking.
  • Normalisatie is een andere afspraak dan hoofdletters aanpassen of witruimte verwijderen.

Hierna zet je tekst om naar bytes en lees je zulke gegevens weer terug.

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.