Alle Originalinhalte werden auf Ukrainisch erstellt. Noch nicht alle Inhalte wurden übersetzt. Einige Beiträge sind möglicherweise nur auf Ukrainisch verfügbar.Mehr erfahren
Dieser Inhalt wurde automatisch aus dem Ukrainischen übersetzt.
Die Sortierung von Text scheint eine einfache Aufgabe zu sein – bis man auf das ukrainische Alphabet in Ruby stößt.
["ґ", "г", "є", "е", "і", "и", "ї", "й"].sort

=> ["г", "е", "и", "й", "є", "і", "ї", "ґ"]
Wie wir sehen, ist "ґ" ganz am Ende gelandet. Aber im ukrainischen Alphabet sollte es umgekehrt sein: "ґ" steht nach "г".

Unicode ≠ Alphabet

Ruby sortiert Zeichenfolgen standardmäßig nach Unicode-Codepunkten, also nach der technischen Reihenfolge der Zeichen in der Unicode-Tabelle, und nicht nach der grammatikalischen Reihenfolge der Buchstaben in der ukrainischen Sprache.
uk_alphabet = "АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"
puts "Große Buchstaben:"
uk_alphabet.each_char do |char|
  dec = char.ord
  hex = dec.to_s(16).upcase.rjust(4, '0')
  puts "#{char} -> dec: #{dec}, hex: U+#{hex}"
end

puts "\nKleine Buchstaben:"
uk_alphabet.downcase.each_char do |char|
  dec = char.ord
  hex = dec.to_s(16).upcase.rjust(4, '0')
  puts "#{char} -> dec: #{dec}, hex: U+#{hex}"
end
Große Buchstaben:
А -> dec: 1040, hex: U+0410
Б -> dec: 1041, hex: U+0411
В -> dec: 1042, hex: U+0412
Г -> dec: 1043, hex: U+0413
Ґ -> dec: 1168, hex: U+0490
Д -> dec: 1044, hex: U+0414
Е -> dec: 1045, hex: U+0415
Є -> dec: 1028, hex: U+0404
Ж -> dec: 1046, hex: U+0416
З -> dec: 1047, hex: U+0417
И -> dec: 1048, hex: U+0418
І -> dec: 1030, hex: U+0406
Ї -> dec: 1031, hex: U+0407
Й -> dec: 1049, hex: U+0419
К -> dec: 1050, hex: U+041A
Л -> dec: 1051, hex: U+041B
М -> dec: 1052, hex: U+041C
Н -> dec: 1053, hex: U+041D
О -> dec: 1054, hex: U+041E
П -> dec: 1055, hex: U+041F
Р -> dec: 1056, hex: U+0420
С -> dec: 1057, hex: U+0421
Т -> dec: 1058, hex: U+0422
У -> dec: 1059, hex: U+0423
Ф -> dec: 1060, hex: U+0424
Х -> dec: 1061, hex: U+0425
Ц -> dec: 1062, hex: U+0426
Ч -> dec: 1063, hex: U+0427
Ш -> dec: 1064, hex: U+0428
Щ -> dec: 1065, hex: U+0429
Ь -> dec: 1068, hex: U+042C
Ю -> dec: 1070, hex: U+042E
Я -> dec: 1071, hex: U+042F

Kleine Buchstaben:
а -> dec: 1072, hex: U+0430
б -> dec: 1073, hex: U+0431
в -> dec: 1074, hex: U+0432
г -> dec: 1075, hex: U+0433
ґ -> dec: 1169, hex: U+0491
д -> dec: 1076, hex: U+0434
е -> dec: 1077, hex: U+0435
є -> dec: 1108, hex: U+0454
ж -> dec: 1078, hex: U+0436
з -> dec: 1079, hex: U+0437
и -> dec: 1080, hex: U+0438
і -> dec: 1110, hex: U+0456
ї -> dec: 1111, hex: U+0457
й -> dec: 1081, hex: U+0439
к -> dec: 1082, hex: U+043A
л -> dec: 1083, hex: U+043B
м -> dec: 1084, hex: U+043C
н -> dec: 1085, hex: U+043D
о -> dec: 1086, hex: U+043E
п -> dec: 1087, hex: U+043F
р -> dec: 1088, hex: U+0440
с -> dec: 1089, hex: U+0441
т -> dec: 1090, hex: U+0442
у -> dec: 1091, hex: U+0443
ф -> dec: 1092, hex: U+0444
х -> dec: 1093, hex: U+0445
ц -> dec: 1094, hex: U+0446
ч -> dec: 1095, hex: U+0447
ш -> dec: 1096, hex: U+0448
щ -> dec: 1097, hex: U+0449
ь -> dec: 1100, hex: U+044C
ю -> dec: 1102, hex: U+044E
я -> dec: 1103, hex: U+044F

Folgen der Unicode-Reihenfolge

Da die Unicode-Codes nicht in alphabetischer Reihenfolge angeordnet sind, ergibt die standardmäßige Sortierung in Ruby eine falsche Reihenfolge für ukrainische Wörter, insbesondere für die Buchstaben "ґ", "є", "і", "ї".

Meine Lösung: ukrainian_sort - Ruby-Gem für die korrekte Sortierung ukrainischer Wörter

Um dieses Problem in meinen persönlichen Projekten zu vermeiden, habe ich die Bibliothek ukrainian_sort erstellt, die die Sortierung nach dem offiziellen ukrainischen Alphabet implementiert. Ich habe sie für die Nutzung in meinen Nebenprojekten entwickelt.
Sie vergleicht Wörter Buchstabe für Buchstabe und verwendet dabei die eigene Reihenfolge:
["г", "ґ", "е", "є", "и", "і", "ї", "й"]
require 'ukrainian_sort'

words = ["ґава", "груша", "єнот", "яблуко"]
sorted_words = UkrainianSort.sort(words)
puts sorted_words
# => ["груша", "ґава", "єнот", "яблуко"]
So sortiert Ruby "out of the box":
words.sort
=> ["груша", "яблуко", "єнот", "ґава"]

Warum funktioniert es im Englischen "normal"?

Das englische Alphabet ist eine einfache Reihe von lateinischen Buchstaben von A bis Z in einem durchgehenden Unicode-Bereich (U+0041–U+005A für Großbuchstaben und U+0061–U+007A für Kleinbuchstaben). Das bedeutet, dass die Reihenfolge der Zeichen in Unicode mit der alphabetischen Reihenfolge der englischen Sprache übereinstimmt.
Daher funktioniert die standardmäßige Sortierung in Ruby (Array#sort oder String#<=>), die Zeichen nach ihren Unicode-Codes vergleicht, korrekt für englische Wörter.

In welchen anderen Sprachen gibt es ein Sortierungsproblem?

Die Antwort ist einfach – in vielen. Viele andere Sprachen haben komplexere Alphabete, bei denen die Reihenfolge der Buchstaben in Unicode nicht mit der linguistischen Reihenfolge übereinstimmt, zum Beispiel:
  • Deutsch – wo ä, ö, ü, ß eine besondere Reihenfolge haben;
  • Schwedisch – fügt die Buchstaben å, ä, ö nach z hinzu;
  • Tschechisch, Slowakisch, Polnisch – haben diakritische Buchstaben, die in Unicode nicht aufeinander folgen;
  • Französisch, Spanisch, Portugiesisch – verschiedene Sortierungsregeln mit Apostrophen, Tilden, Akzenten.

Die Komplexität des Problems

Unicode legt eine universelle Zeichenkennung fest, definiert jedoch nicht die linguistische Sortierreihenfolge. Für die korrekte Sortierung von Sprachen sind oft spezielle Regeln erforderlich – Sortierregeln, die Folgendes berücksichtigen:
  • Die Reihenfolge der Buchstaben,
  • Besondere Zeichen,
  • Akzente
  • Ob Groß- und Kleinbuchstaben gleich behandelt werden,
  • Ligaturen und andere sprachliche Besonderheiten.

Wie wird das normalerweise gelöst?

  • Durch lokalisierte Sortierer (z.B. ICU – International Components for Unicode). Aber ich konnte schnell keine Lösung für mich finden.
  • Spezielle Bibliotheken für die Sortierung (Gems, Pakete).
  • Manuelle Festlegung der Reihenfolge für eine bestimmte Sprache.
Für die englische Sprache stimmt die Unicode-Sequenz der Zeichen mit der alphabetischen Reihenfolge überein, sodass sortieren problemlos funktioniert. Aber für die meisten anderen Sprachen müssen die linguistischen Sortierungsregeln zusätzlich berücksichtigt werden, denn Unicode ist nur eine Kodierungstabelle und kein Sortieralgorithmus.
ukrainian_sort (GitHub / RubyGems) – eines der ersten Gems, die ich öffentlich veröffentlicht habe. Normalerweise mache ich private Repositories mit Lösungen für mich selbst. Daher könnt ihr gerne Issues und Pull-Requests erstellen. Wahrscheinlich gibt es dort noch einiges zu verbessern.

Dieser Beitrag hat noch keine Ergänzungen vom Autor.