乐趣区

关于php: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() 办法就能够实现对中文字符的拼音排序。

$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

各自媒体平台均可搜寻【硬核项目经理】

退出移动版