Kies de NFC-vorm
Laat normalise de NFC-vorm van de tekst teruggeven. Stel losse accenten waar mogelijk samen en behoud al genormaliseerde tekst.
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.
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.
| Opbouw | Aantal codepunten | Uiterlijk |
|---|---|---|
Eén voorgevormde letter ë | 1 | ë |
| De letter e plus een los trema | 2 | ë |
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.
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.
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)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.
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.
name = "cafe\u0301"
print(name.lower() == "café")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.
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.
Laat normalise de NFC-vorm van de tekst teruggeven. Stel losse accenten waar mogelijk samen en behoud al genormaliseerde tekst.
Laat normalise de NFC-afspraak volgen: vervang een brede letter, ligatuur of omcirkeld cijfer niet door gewone tekens.
Laat same_text een boolean teruggeven die de NFC-vorm van beide teksten vergelijkt. Hoofdletters blijven betekenisvol.
Laat normalise alleen de NFC-bewerking doen. Verwijder geen witruimte en verander geen hoofdletters; lege tekst blijft geldig.
Hierna zet je tekst om naar bytes en lees je zulke gegevens weer terug.
Voer je code uit en ontdek
wat je hebt gemaakt.
Je hoeft het niet in één keer goed te doen. Na het uitvoeren zie je hier welke stappen al kloppen.