一、UCA 簡介
Unicode Collation Algorithm (UCA) 是 Unicode 規定的如何比較兩個字符串大小的算法,也是事實上的標准。我們先來看下它的幾個特征。
1.1 Multi-Level Comparison
為了處理字符串比較的復雜性,UCA 采用了多級比較的方法。
當比較兩個字符串時,先比較最重要的特征——字母。如果字母相同,再比較重音 (accent)。如果重音還相同,再比較大小寫。依次類推,這些特征之間的順序可以改變。

如上圖所示,首先比較基本字符串,然后依次是 Accent、 Case、Punctuation等,最后比較是否完全相等。
一定要注意,Unicode 碼點的順序不是排序的依據。
The position of characters in the Unicode code charts does not specify their sort order.
為何要采樣多級比較
考慮一個例子,我們有a < ä && e < ë && a < e && ä < ë,如果我們僅僅采用單級比較的話,顯然有a < ä < e < ë。
比較字符串ae和äa。我們想要得到的結果肯定是äa < ae。如果按照單級比較的話,由於a < ä,我們會得到ae < äa。
使用多級比較,可以優先處理主要矛盾。
1.2 Canonical Equivalence
在 Unicode 中,可能出現兩個不同碼點序列表示的是同一個字符串,即這兩個序列具有 Unicode等價性。這些具有 Unicode 等價性的字符串在排序時,應該被認為是同樣的。下表是一些 Unicode 等價性的例子。

1.3 Contextual Sensitivity
在某些語言中,字符串的比較不僅僅是單個字符序列的比較,和字符出現的上下文有關。UCA 必須處理好這些事情,如下所示:

1.4 Customization
在實際使用中,UCA 應該可以處理一些用戶自定義的規則,包括但不限於:
- Language。
排序結果應該符號目標語言使用者的預期。 - Case Ordering
有時大寫在前,有時小寫在前。 - Script Order
用戶可能希望一種文字出現在另一種文字之前。
b < ב < β < б [Latin < Hebrew < Greek < Cyrillic] versus
β < b < б < ב [Greek < Latin < Cyrillic < Hebrew] - Numbers
用戶可能希望把字符串按照數字排序,如A2 < A10。
二、UCA 排序算法處理過程
2.1 Normalize
使用 Unicode 規范化算法,把字符串以標准等價方式來分解 (Normalization Form Canonical Decomposition, NFD)。
2.2 Produce Array
對字符串中的每一個字符進行多級量化,轉化為數組,便於之后的比較。

如上所示,每一個字符對應一個 collation element;每一個元素中用.分隔不同等級的權重的值。比如c的第一權重是0706,第二權重是0020,第三權重是0002。
2.3 Form Sort Key
把數組中所有非零權重的值按照等級連接起來,組成一個 sort key。


如果指定了只比較等級 1、2,那么等級 3 就不會在 sort key 中出現。
2.4 Compare
使用一種方法對字符串的 sort key 進行排序。下面是一個排序結果的例子。

最后的排序結果是"cab" <<< "Cab" << "cáb" < "dab$"。
- 對於字符串 1 和 2,第一個區別是 0002 VS 0008 (Level 3).
- 對於字符串 2 和 3,第一個區別是 0020 VS 0021 (Level 2).
- 對於字符串 3 和 4,第一個區別是 0706 VS 0712 (Level 1).
三、其他
- 生成Collation Element 時,具體的值可以被修改
CLDR 指定了如何根據語言和地區進行處理,還包括其他內容。 -
字符串有時需要預處理
在某些具體的情形下,需要進行預處理,下面是一些例子。- McBeth -> MacBeth
- St. -> Saint 或者 St. -> Street
- 去掉冠詞
- 加入額外信息。對於漢字來說,有多音字。
-
UCA 只是規定了一個算法。具體的實現可以不同,只要保證和 UCA 結果相同。
四、參考
