$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() 方法就可以完成对中笔墨符的拼音排序。

$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() 方法还支持第二个参数,用于指定当前的排序是按照字符还是数字格式进行排序。
对付纯中文的内容来说,这个没有什么差异。

php中文字符比较PHP中国际化的字符串比拟对象 React

除了 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