Вот некоторый код Javascript, который пытается найти кодовую точку Unicode, чье представление UTF-8 сжимается больше всего при преобразовании в NFD и обратно в NFC.Кажется, что ни одна кодовая точка не уменьшается более чем в три раза.Насколько я понимаю алгоритм нормализации Unicode, таким способом нужно проверять только отдельные кодовые точки.
Я думаю, что, по крайней мере теоретически, это может измениться в будущих версиях Unicode.Но существует политика стабильности относительно расширения строк при нормализации в NFC (см. Также Может ли нормализация Unicode NFC увеличить длину строки? ), поэтому я думаю,маловероятно, что это когда-либо изменится:
Канонические отображения (значения свойств Decomposition_Mapping) всегда ограничены, так что ни одна строка при нормализации к NFC не увеличивается в длину более чем в 3 раза (измеряется в единицах кода).
Таким образом, выделение начального буфера, в три раза превышающего максимальную длину строки, кажется разумным выбором.
var maxRatio = 2;
var codePoints = [];
for (var i=0; i<0x110000; i++) {
// Exclude surrogates
if (i >= 0xD800 && i <= 0xDFFF) continue;
var nfd = String.fromCodePoint(i).normalize('NFD');
var nfc = nfd.normalize('NFC');
var nfdu8 = unescape(encodeURIComponent(nfd));
var nfcu8 = unescape(encodeURIComponent(nfc));
var ratio = nfdu8.length / nfcu8.length;
if (ratio > maxRatio) {
maxRatio = ratio;
codePoints = [ i ];
}
else if (ratio == maxRatio) {
codePoints.push(i);
}
}
console.log(`Max ratio: ${maxRatio}`);
for (codePoint of codePoints) {
// Exclude Hangul syllables
if (codePoint >= 0xAC00 && codePoint <= 0xD7AF) continue;
var nfd = String.fromCodePoint(codePoint).normalize('NFD');
var nfc = nfd.normalize('NFC');
console.log(
codePoint.toString(16).toUpperCase(),
encodeURIComponent(nfd),
encodeURIComponent(nfc)
);
}