PHP中國際化的字串比較物件
在PHP 中,國際化的功能非常豐富,包括許多我們可能都不知道的東西其實都很有用,例如說今天要介紹的這一系列的字元排序和比較的功能。
排序
正常來說,如果我們對陣列中的字元進行排序,按照的是字元的ASC2 表的順序進行排列,如果是英文還好,但對於中文的話,排序出來的結果會是非常懵逼的。
$arr = ['我','是','硬','核','项', '目', '经', '理']; sort($arr); var_dump( $arr ); // array(8) { // [0]=> // string(3) "我" // [1]=> // string(3) "是" // [2]=> // string(3) "核" // [3]=> // string(3) "理" // [4]=> // string(3) "目" // [5]=> // string(3) "硬" // [6]=> // string(3) "经" // [7]=> // string(3) "项" // }
按照我們的習慣會以中文的拼音來對漢字進行排序,這個時候往往大家都會選擇自己寫排序的演算法或去找合適的 Composer 套件。其實,PHP 中已經為我們準備了一個物件就是用來處理這類問題的。
$coll = new Collator( 'zh_CN' ); $coll->sort($arr); var_dump( $arr ); // array(8) { // [0]=> // string(3) "核" // [1]=> // string(3) "经" // [2]=> // string(3) "理" // [3]=> // string(3) "目" // [4]=> // string(3) "是" // [5]=> // string(3) "我" // [6]=> // string(3) "项" // [7]=> // string(3) "硬" // }
沒錯,就是這個 Collator 類別。它在實例化的時候需要指定目前的區域,例如我們指定為 zh_CN ,也就是中文字元區域,這時候再使用它的 sort() 方法就可以完成對中文字元的拼音排序。 (建議:PHP影片教學)
$coll->sort($arr, Collator::SORT_NUMERIC ); var_dump( $arr ); // array(8) { // [0]=> // string(3) "核" // [1]=> // string(3) "经" // [2]=> // string(3) "理" // [3]=> // string(3) "目" // [4]=> // string(3) "是" // [5]=> // string(3) "我" // [6]=> // string(3) "项" // [7]=> // string(3) "硬" // } $coll->sort($arr, Collator::SORT_STRING ); var_dump( $arr ); // array(8) { // [0]=> // string(3) "核" // [1]=> // string(3) "经" // [2]=> // string(3) "理" // [3]=> // string(3) "目" // [4]=> // string(3) "是" // [5]=> // string(3) "我" // [6]=> // string(3) "项" // [7]=> // string(3) "硬" // }
Collator 物件的 sort() 方法也支援第二個參數,用於指定目前的排序是依照字元還是數字格式進行排序。對於純中文的內容來說,這沒有什麼差別。
除了 sort() 方法之外,它還有一個 asort() 方法,就和普通的 asort() 函數一樣的功能,只不過它也是支援不同的區域語言的。
$arr = [ 'a' => '100', 'b' => '7', 'c' => '50' ]; $coll->asort($arr, Collator::SORT_NUMERIC ); var_dump( $arr ); // array(3) { // ["b"]=> // string(1) "7" // ["c"]=> // string(2) "50" // ["a"]=> // string(3) "100" // } $coll->asort($arr, Collator::SORT_STRING ); var_dump( $arr ); // array(3) { // ["a"]=> // string(3) "100" // ["c"]=> // string(2) "50" // ["b"]=> // string(1) "7" // } $arr = [ '中' => '100', '的' => '7', '文' => '50' ]; $coll->asort($arr, Collator::SORT_NUMERIC ); var_dump( $arr ); // array ( // '的' => '7', // '文' => '50', // '中' => '100', // ) $coll->asort($arr, Collator::SORT_STRING ); var_dump( $arr ); // array ( // '中' => '100', // '文' => '50', // '的' => '7', // )
asrot() 方法是根據鍵和值一起進行排序的,所以在這裡指定 SORT_STRING 和 SORT_NUMERIC 就有明顯的效果了。我們可以看出,如果是根據數字排序,那麼結果就是以數字內容為準的,如果是根據字元排序,那麼結果就是以鍵值中的字串部分為基礎進行排序的。
不管是 sort() 或 asrot() 本質上都和普通的 PHP 預設提供的 sort() 和 asrot() 函數一樣的。只是它們多了區域語言的功能而已。
另外,Collator 物件中也提供了一個 sortWithSortKeys() 方法,這個是普通的 PHP 排序函數中沒有的。
$arr = ['我','是','硬','核','项', '目', '经', '理']; $coll->sortWithSortKeys($arr); var_dump( $arr ); // array ( // 0 => '核', // 1 => '经', // 2 => '理', // 3 => '目', // 4 => '是', // 5 => '我', // 6 => '项', // 7 => '硬', // )
它與 sort() 方法是類似的,但使用的是 ucol_getSortKey() 來產生的 ICU 排序鍵,在大型陣列上的速度更快。
ICU 的全名為 International Components for Unicode ,也就是 Unicode 的國際化元件,它提供了翻譯相關的功能,也就是我們系統中以及各類程式語言要實現國際化能力的基礎。
比較
接下來就是字串的比較,比如說我們都知道,"a" 是比"A" 要大的,因為在ASC2 碼表中,"A" 是65 ,"a" 是97 。當然,這只是預設的比較,在使用 Collator 物件的函數進行比較時,則是根據字典庫中的排序索引進行比較的,對於中文來說,基本上就也是按照拼音的順序來比較了。
var_dump($coll->compare('Hello', 'hello')); // int(1) var_dump($coll->compare('你好', '您好')); // int(-1)
compare() 方法就是用來進行比較的,如果兩個字串相等,回傳的就是0 ,如果第一個字串大於第二個,回傳的是1 ,否則回傳的是-1 。從程式碼中,我們可以看出 "Hello" 是大於 "hello" 的,"你好" 是小於 "您好" 的( 因為 "您" 多了一個 g )。
屬性設定
Collator 物件中也可以設定一些物件的屬性。
$coll->setAttribute(Collator::CASE_FIRST, Collator::UPPER_FIRST); var_dump($coll->getAttribute(Collator::CASE_FIRST)); // int(25) var_dump($coll->compare('Hello', 'hello')); // int(-1) $coll->setAttribute(Collator::CASE_FIRST, Collator::LOWER_FIRST); var_dump($coll->getAttribute(Collator::CASE_FIRST)); // int(24) var_dump($coll->compare('Hello', 'hello')); // int(1) $coll->setAttribute(Collator::CASE_FIRST, Collator::OFF); var_dump($coll->getAttribute(Collator::CASE_FIRST)); // int(16) var_dump($coll->compare('Hello', 'hello')); // int(1)
這裡我們是為物件指定 CASE_FIRST 屬性,屬性值可以指定 大寫優先、小寫優先 之類的,對於英文字元來說,這個可以影響排序以及對比的結果。
另外,我們也可以透過一個方法來獲得目前區域語言的資訊。
var_dump($coll->getLocale(Locale::VALID_LOCALE)); // string(10) "zh_Hans_CN" var_dump($coll->getLocale(Locale::ACTUAL_LOCALE)); // string(2) "zh"
這兩個參數分別是獲得有效的區域設定資訊和實際的區域資訊。
排序資訊
當然,我們也可以看到具體的排序訊息,也就是在 Collator 中字元的編碼。
var_dump(bin2hex($coll->getSortKey('Hello'))); // string(20) "b6b0bebec4010901dc08" var_dump(bin2hex($coll->getSortKey('hello'))); // string(18) "b6b0bebec401090109" var_dump(bin2hex($coll->getSortKey('你好'))); // string(16) "7b9b657301060106" var_dump(bin2hex($coll->getSortKey('您好'))); // string(16) "7c33657301060106" $coll = collator_create( 'en_US' ); var_dump($coll->compare('Hello', 'hello')); // int(1) var_dump($coll->compare('你好', '您好')); // int(-1) var_dump($coll->getLocale(Locale::VALID_LOCALE)); // string(5) "en_US" var_dump($coll->getLocale(Locale::ACTUAL_LOCALE)); // string(4) "root" var_dump(bin2hex($coll->getSortKey('Hello'))); // string(20) "3832404046010901dc08" var_dump(bin2hex($coll->getSortKey('hello'))); // string(18) "383240404601090109" var_dump(bin2hex($coll->getSortKey('你好'))); // string(20) "fb0b8efb649401060106" var_dump(bin2hex($coll->getSortKey('您好'))); // string(20) "fba5f8fb649401060106"
可以看出,不用同的區域語言取得到的 getSortKey() 排序鍵資訊是不同的,不過它們都是以 16進位 儲存的,這和預設的 ASC2 碼完全不同了。
錯誤訊息
$coll = new Collator( 'en_US' );; $coll->compare( 'y', 'k' ); var_dump($coll->getErrorCode()); // int(0) var_dump($coll->getErrorMessage()); // string(12) "U_ZERO_ERROR"
使用 getErrorCode() 可以取得錯誤碼,使用 getErrorMessage() 可以取得錯誤訊息。關於返回的這個 U_ZERO_ERROR 並沒有查找到相關的資料,希望懂行的朋友可以回覆說明,大家一起學習。
排序規則強度
另外就是 Collator 物件就還有一個排序強度的設定,不過我測試的效果並沒有體現出來。
$arr = array( 'a', 'à' ,'A'); $coll = new Collator( 'de_DE' ); $coll->sort($arr); var_dump($coll->getStrength()); var_dump( $arr ); // int(2) // array(3) { // [0]=> // string(1) "a" // [1]=> // string(1) "A" // [2]=> // string(2) "à" // } $coll->setStrength(Collator::IDENTICAL); var_dump($coll->getStrength()); // int(15) $coll->sort($arr); var_dump( $arr ); $coll->setStrength(Collator::QUATERNARY); var_dump($coll->getStrength()); // int(3) $coll->sort($arr); var_dump( $arr ); $coll->setStrength(Collator::PRIMARY); var_dump($coll->getStrength()); // int(0) $coll->sort($arr ); var_dump( $arr ); $coll->setStrength(Collator::TERTIARY); var_dump($coll->getStrength()); // int(2) $coll->sort($arr ); var_dump( $arr ); $coll->setStrength(Collator::SECONDARY); var_dump($coll->getStrength()); // int(1) $coll->sort($arr ); var_dump( $arr );
在官方文件的測試程式碼的結果中,指定不同的參數會傳回不同的排序順序,但我實際測試的結果卻全都是一樣的。所以這裡就不做講解了,因為自己也沒搞懂為什麼。大家了解一下即可,如果有清楚這方面知識的朋友也請留言回覆一起學習!
總結
#很有意思的一个对象吧,其实这个对象也是支持面向过程式的函数写法的,在示例代码中也有使用面向过程的方式的调用的。总体来说,按拼音排序和比较这两个功能在实际的开发中相信还是有不少用武之地的,大家可以尝试看看哦!
测试代码: https://github.com/zhangyue0503/dev-blog/blob/master/php/202011/source/3.PHP中国际化的字符串比较对象.php 参考文档: https://www.php.net/manual/zh/class.collator.php
以上是PHP中國際化的字串比較對象的詳細內容。更多資訊請關注PHP中文網其他相關文章!