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

$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

关注公众号:【硬核项目经理】获取最新文章

添加微信/QQ好友:【xiaoyuezigonggong/149844827】免费得PHP、项目管理学习资料

知乎、公众号、抖音、头条搜索【硬核项目经理】

B站ID:482780532

PHP中国际化的字符串比较对象的更多相关文章

  1. js中数组,字符串,对象常用方法总结

    时间对象方法 获取当前时间的毫秒数 1.var timestamp = Date.parse(new Date()); 2.var timestamp = (new Date()).valueOf() ...

  2. javascript中遇到的字符串对象处理

    在javascript中对参数处理: 1 <script> 2 function getParam() 3 { 4 urlInfo=window.location.href; //获取当前 ...

  3. js String对象中常用方法小结(字符串操作)

    1.charCodeAt方法返回一个整数,代表指定位置字符的Unicode编码. strObj.charCodeAt(index) 说明: index将被处理字符的从零开始计数的编号.有效值为0到字符 ...

  4. js 判断字符串是否包含某字符串,String对象中查找子字符,indexOf

    var Cts = "bblText";   if(Cts.indexOf("Text") > 0 ) {     alert('Cts中包含Text字符 ...

  5. 客户端、服务器端中JSON字符串与对象的转换

    客户端: 字符串转为对象:$.parseJSON(json); 对象转为字符串:JSON.stringify(_pasteDataItem) 服务器端(c#): 对象: [DataContract(N ...

  6. (转)解决fasterxml中string字符串转对象json格式错误问题(无引号 单引号问题)

    原文地址:解决fasterxml中string字符串转对象json格式错误问题 com.fasterxml.jackson.databind.ObjectMapper mapper = new com ...

  7. js中console在一行内打印字符串和对象

    在前端开发中,大多数的调试一般都是F12中的console和network中查看请求数据和响应数据,也有一部分人喜欢用debugger. 在开发大一些的项目时,在开发环境下,打开着控制台,切换一下页面 ...

  8. [转载]js javascript 判断字符串是否包含某字符串,String对象中查找子字符,indexOf

    var Cts = "bblText"; if(Cts.indexOf("Text") > 0 ) { alert('Cts中包含Text字符串'); }

  9. js中json字符串与对象的转换及是否为空

    1.json对象(数组)转字符串 var b=[ { "CategoryName" : "Beverages", "ProductName" ...

随机推荐

  1. Element Vue 开箱即用框架如何使用-测试开发【提测平台】阶段小结(二)

    微信搜索[大奇测试开],关注这个坚持分享测试开发干货的家伙. 上一篇总结了后端服务接口的开发,这篇我们主要来总结下前后端分离开发中的前端部分,主要是开箱即用的框架介绍和之前章节组件的梳理和部分的扩展内 ...

  2. docker 安装部署 redis(配置文件启动)

    获取 redis 镜像 docker pull redis:4.0.12 docker images 创建容器 创建宿主机 redis 容器的数据和配置文件目录 # 创建宿主机 redis 容器的数据 ...

  3. C#中的几种锁:用户模式锁、内核模式锁、动态计数、监视锁

    参考网址: https://blog.csdn.net/weixin_43989331/article/details/105356008 C#中的几种锁:用户模式锁.内核模式锁.动态计数.监视锁介绍 ...

  4. PostgreSQL执行计划的解析

    一个顺序磁盘页面操作的cost值由系统参数seq_page_cost (floating point)参数指定的,由于这个参数默认为1.0,所以我们可以认为一次顺序磁盘页面操作的cost值为1.下面o ...

  5. 翻译Go Blog: 常量

    常量 Pob Pike 2014年8月24日 原文 介绍 Go是一门静态语言,它不允许不同数字类型间的操作.你不能将一个浮点数(float64)和一个整数(int)相加,也不能将一个32位整数(int ...

  6. 有关Java动态数组的一个小问题

    前言 问题描述 今天遇到一个关于集合的问题,觉得比较有趣,记录一下,这个问题是:定义一个用户类,至少包含姓名,年龄,生日,qq邮箱,初始化10个用户,利用String操作,提取qq到List集合中,姓 ...

  7. 高德地图——步行路线&步行路线的坐标规划

    步行操作与开车一样 唯一区别就是src末尾加入&plugin=AMap.Walkling 以及new AMap.Walking({}) <!DOCTYPE html> <ht ...

  8. 硬核! Github上 ,star超高的Java 开源项目分享给你!

    Awsome JavaGreat Java project on Github(Github 上非常棒的 Java 开源项目). English Version 大家都知道 Github 是一个程序员 ...

  9. 设置 Qt GUI程序 printf输出到独立控制台

  10. Data Leakage in Machine Learning 机器学习训练中的数据泄漏

    refer to:  https://www.kaggle.com/dansbecker/data-leakage There are two main types of leakage: Leaky ...