目錄
- 前言
- 排序
- 比較
- 屬性設(shè)置
- 排序信息
- 錯誤信息
- 排序規(guī)則強度
- 總結(jié)
前言
在 PHP 中,國際化的功能非常豐富,包括很多我們可能都不知道的東西其實都非常有用,比如說今天要介紹的這一系列的字符排序和比較的功能。
排序
正常來說,如果我們對數(shù)組中的字符進行排序,按照的是字符的 ASC2 表的順序進行排列,如果是英文還好,但對于中文的話,排序出來的結(jié)果會是非常懵逼的。
$arr = ['我','是','硬','核','項', '目', '經(jīng)', '理'];
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) "經(jīng)"
// [7]=>
// string(3) "項"
// }
按照我們的習慣會以中文的拼音來對漢字進行排序,這個時候往往大家都會選擇自己寫排序的算法或者去找合適的 Composer 包。其實,PHP 中已經(jīng)為我們準備了一個對象就是用來處理這類問題的。
$coll = new Collator( 'zh_CN' );
$coll->sort($arr);
var_dump( $arr );
// array(8) {
// [0]=>
// string(3) "核"
// [1]=>
// string(3) "經(jīng)"
// [2]=>
// string(3) "理"
// [3]=>
// string(3) "目"
// [4]=>
// string(3) "是"
// [5]=>
// string(3) "我"
// [6]=>
// string(3) "項"
// [7]=>
// string(3) "硬"
// }
沒錯,正是這個 Collator 類。它在實例化的時候需要指定當前的區(qū)域,比如我們指定為 zh_CN ,也就是中文字符區(qū)域,這時候再使用它的 sort() 方法就可以完成對中文字符的拼音排序。
$coll->sort($arr, Collator::SORT_NUMERIC );
var_dump( $arr );
// array(8) {
// [0]=>
// string(3) "核"
// [1]=>
// string(3) "經(jīng)"
// [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) "經(jīng)"
// [2]=>
// string(3) "理"
// [3]=>
// string(3) "目"
// [4]=>
// string(3) "是"
// [5]=>
// string(3) "我"
// [6]=>
// string(3) "項"
// [7]=>
// string(3) "硬"
// }
Collator 對象的 sort() 方法還支持第二個參數(shù),用于指定當前的排序是按照字符還是數(shù)字格式進行排序。對于純中文的內(nèi)容來說,這個沒有什么區(qū)別。
除了 sort() 方法之外,它還有一個 asort() 方法,就和普通的 asort() 函數(shù)一樣的功能,只不過它也是支持不同的區(qū)域語言的。
$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() 方法是根據(jù)鍵和值一起進行排序的,所以在這里指定 SORT_STRING 和 SORT_NUMERIC 就有明顯的效果了。我們可以看出,如果是根據(jù)數(shù)字排序,那么結(jié)果就是以數(shù)字內(nèi)容為準的,如果是根據(jù)字符排序,那么結(jié)果就是以鍵值中的字符串部分為基礎(chǔ)進行排序的。
不管是 sort() 還是 asrot() 本質(zhì)上都和普通的 PHP 默認提供的 sort() 和 asrot() 函數(shù)一樣的。只是它們多了區(qū)域語言的功能而已。
另外,Collator 對象中還提供了一個 sortWithSortKeys() 方法,這個是普通的 PHP 排序函數(shù)中沒有的。
$arr = ['我','是','硬','核','項', '目', '經(jīng)', '理'];
$coll->sortWithSortKeys($arr);
var_dump( $arr );
// array (
// 0 => '核',
// 1 => '經(jīng)',
// 2 => '理',
// 3 => '目',
// 4 => '是',
// 5 => '我',
// 6 => '項',
// 7 => '硬',
// )
它與 sort() 方法是類似的,但使用的是 ucol_getSortKey() 來生成的 ICU 排序鍵,在大型數(shù)組上的速度更快。
ICU 的全稱是 International Components for Unicode ,也就是 Unicode 的國際化組件,它提供了翻譯相關(guān)的功能,也就是我們系統(tǒng)中以及各類編程語言要實現(xiàn)國際化能力的基礎(chǔ)。
比較
接下來就是字符串的比較,比如說我們都知道,"a" 是比 "A" 要大的,因為在 ASC2 碼表中,"A" 是 65 ,"a" 是 97 。當然,這只是默認情況下的比較,在使用 Collator 對象的函數(shù)進行比較時,則是根據(jù)字典庫中的排序索引進行比較的,對于中文來說,基本上就也是按照拼音的順序來比較了。
var_dump($coll->compare('Hello', 'hello')); // int(1)
var_dump($coll->compare('你好', '您好')); // int(-1)
compare() 方法就是用來進行比較的,如果兩個字符串相等,返回的就是 0 ,如果第一個字符串大于第二個,返回的是 1 ,否則返回的是 -1 。從代碼中,我們可以看出 "Hello" 是大于 "hello" 的,"你好" 是小于 "您好" 的( 因為 "您" 多了一個 g )。
屬性設(shè)置
Collator 對象中還可以設(shè)置一些對象的屬性。
$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 屬性,屬性值可以指定 大寫優(yōu)先、小寫優(yōu)先 之類的,對于英文字符來說,這個可以影響排序以及對比的結(jié)果。
另外,我們還可以通過一個方法獲得當前區(qū)域語言的信息。
var_dump($coll->getLocale(Locale::VALID_LOCALE)); // string(10) "zh_Hans_CN"
var_dump($coll->getLocale(Locale::ACTUAL_LOCALE)); // string(2) "zh"
這兩個參數(shù)分別是獲得有效的區(qū)域設(shè)置信息和實際的區(qū)域信息。
排序信息
當然,我們也可以看到具體的排序信息,也就是字符在 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"
可以看出,不用同的區(qū)域語言獲取到的 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() 可以獲得錯誤信息。關(guān)于返回的這個 U_ZERO_ERROR 并沒有查找到相關(guān)的資料,希望懂行的朋友可以回復(fù)說明,大家一起學習。
排序規(guī)則強度
另外就是 Collator 對象就還有一個排序強度的設(shè)定,不過我測試的效果并沒有體現(xiàn)出來。
$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 );
在官方文檔的測試代碼的結(jié)果中,指定不同的參數(shù)會返回不同的排序順序,但我實際測試的結(jié)果卻全都是一樣的。所以這里就不做講解了,因為自己也沒搞明白為什么。大家了解一下即可,如果有清楚這方面知識的朋友也請留言回復(fù)一起學習哦!
總結(jié)
很有意思的一個對象吧,其實這個對象也是支持面向過程式的函數(shù)寫法的,在示例代碼中也有使用面向過程的方式的調(diào)用的。總體來說,按拼音排序和比較這兩個功能在實際的開發(fā)中相信還是有不少用武之地的,大家可以嘗試看看哦!
測試代碼:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202011/source/3.PHP中國際化的字符串比較對象.php
參考文檔:
https://www.php.net/manual/zh/class.collator.php
到此這篇關(guān)于PHP中國際化的字符串排序和比較對象的文章就介紹到這了,更多相關(guān)PHP國際化字符串比較對象內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- PHP學習之字符串比較和查找
- PHP字符串比較函數(shù)strcmp()和strcasecmp()使用總結(jié)
- 關(guān)于php幾種字符串連接的效率比較(詳解)
- php實現(xiàn)比較兩個字符串日期大小的方法
- PHP 字符串分割和比較
- php 字符串壓縮方法比較示例
- PHP容易被忽略而出錯陷阱 數(shù)字與字符串比較
- 用PHP中的 == 運算符進行字符串比較
- php比較相似字符串的方法
- php常用字符串比較函數(shù)實例匯總