使用 usort 与 php 的自定义排序规则
Custom collation with php using usort
我正在尝试按自定义字母表对数组进行排序(国际名称,Collator 区域设置的 none 完全按照我想要的顺序排列)。
我从 here 那里窃取了一些代码并拥有。
function compare_by_alphabet($str1, $str2){
$alphabet = "AaÀàÁáÂâÅåÃãÄäÆæBbCcÇçDdÐðEeÈèÉéÊêËëFfGgHhIiÌìÍíÎîÏïJjKkLlMmNnÑñOoÒòÓóÔôÕõÖöØøPpQqRrSsߊšTtUuÙùÚúÛûÜüVvWwXxYyŸÿÝýZzŽžÞþ0123456789";
$l1 = strlen($str1);
$l2 = strlen($str2);
$c = min($l1, $l2);
for ($i = 0; $i < $c; $i++)
{
$s1 = substr($str1, $i, 1);
$s2 = substr($str2, $i, 1);
if ($s1===$s2) continue;
$i1 = strpos($alphabet, $s1);
if ($i1===false) continue;
$i2 = strpos($alphabet, $s2);
if ($i2===false) continue;
if ($i2===$i1) continue;
if ($i1 < $i2) return -1;
else return 1;
}
if ($l1 < $l2) return -1;
elseif ($l1 > $l2) return 1;
return 0;
}
当我尝试时
$names=["Schön","Åsberg","Zierer","Ås","Žižek","Schon","Asber"];
usort($names, 'compare_by_alphabet');
我明白了 ["Asber","Ås","Åsberg","Schön","Schon","Žižek","Zierer"]
- 这两个 Schon 是错误的,齐泽克和齐勒也是如此。
我在这里遗漏了一些东西。有人可以解释为什么这不符合预期吗?或者我该如何解决?
标准 PHP 字符串函数不兼容多字节。在您的示例中,字符串和字母表包含多字节字符(大多数现代 php 编辑器将默认使用 utf-8 encoding)。比如À在utf-8中其实是用2个字节来表示的。
运行 验证以下内容:
php > echo strlen("À");
2
使用multibyte string个函数来解决问题。
应用后,代码为:
function compare_by_alphabet($str1, $str2) {
$alphabet = "AaÀàÁáÂâÅåÃãÄäÆæBbCcÇçDdÐðEeÈèÉéÊêËëFfGgHhIiÌìÍíÎîÏïJjKkLlMmNnÑñOoÒòÓóÔôÕõÖöØøPpQqRrSsߊšTtUuÙùÚúÛûÜüVvWwXxYyŸÿÝýZzŽžÞþ0123456789";
$l1 = mb_strlen($str1);
$l2 = mb_strlen($str2);
$c = min($l1, $l2);
for ($i = 0; $i < $c; $i++)
{
$s1 = mb_substr($str1, $i, 1);
$s2 = mb_substr($str2, $i, 1);
if ($s1===$s2) continue;
$i1 = mb_strpos($alphabet, $s1);
if ($i1===false) continue;
$i2 = mb_strpos($alphabet, $s2);
if ($i2===false) continue;
if ($i2===$i1) continue;
if ($i1 < $i2) return -1;
else return 1;
}
if ($l1 < $l2) return -1;
elseif ($l1 > $l2) return 1;
return 0;
}
$names=["Schön","Åsberg","Zierer","Ås","Žižek","Schon","Asber"];
usort($names, 'compare_by_alphabet');
var_dump($names);
结果
array(7) {
[0]=>string(5) "Asber"
[1]=>string(3) "Ås"
[2]=>string(7) "Åsberg"
[3]=>string(5) "Schon"
[4]=>string(6) "Schön"
[5]=>string(6) "Zierer"
[6]=>string(7) "Žižek"
}
我正在尝试按自定义字母表对数组进行排序(国际名称,Collator 区域设置的 none 完全按照我想要的顺序排列)。
我从 here 那里窃取了一些代码并拥有。
function compare_by_alphabet($str1, $str2){
$alphabet = "AaÀàÁáÂâÅåÃãÄäÆæBbCcÇçDdÐðEeÈèÉéÊêËëFfGgHhIiÌìÍíÎîÏïJjKkLlMmNnÑñOoÒòÓóÔôÕõÖöØøPpQqRrSsߊšTtUuÙùÚúÛûÜüVvWwXxYyŸÿÝýZzŽžÞþ0123456789";
$l1 = strlen($str1);
$l2 = strlen($str2);
$c = min($l1, $l2);
for ($i = 0; $i < $c; $i++)
{
$s1 = substr($str1, $i, 1);
$s2 = substr($str2, $i, 1);
if ($s1===$s2) continue;
$i1 = strpos($alphabet, $s1);
if ($i1===false) continue;
$i2 = strpos($alphabet, $s2);
if ($i2===false) continue;
if ($i2===$i1) continue;
if ($i1 < $i2) return -1;
else return 1;
}
if ($l1 < $l2) return -1;
elseif ($l1 > $l2) return 1;
return 0;
}
当我尝试时
$names=["Schön","Åsberg","Zierer","Ås","Žižek","Schon","Asber"];
usort($names, 'compare_by_alphabet');
我明白了 ["Asber","Ås","Åsberg","Schön","Schon","Žižek","Zierer"]
- 这两个 Schon 是错误的,齐泽克和齐勒也是如此。
我在这里遗漏了一些东西。有人可以解释为什么这不符合预期吗?或者我该如何解决?
标准 PHP 字符串函数不兼容多字节。在您的示例中,字符串和字母表包含多字节字符(大多数现代 php 编辑器将默认使用 utf-8 encoding)。比如À在utf-8中其实是用2个字节来表示的。
运行 验证以下内容:
php > echo strlen("À");
2
使用multibyte string个函数来解决问题。
应用后,代码为:
function compare_by_alphabet($str1, $str2) {
$alphabet = "AaÀàÁáÂâÅåÃãÄäÆæBbCcÇçDdÐðEeÈèÉéÊêËëFfGgHhIiÌìÍíÎîÏïJjKkLlMmNnÑñOoÒòÓóÔôÕõÖöØøPpQqRrSsߊšTtUuÙùÚúÛûÜüVvWwXxYyŸÿÝýZzŽžÞþ0123456789";
$l1 = mb_strlen($str1);
$l2 = mb_strlen($str2);
$c = min($l1, $l2);
for ($i = 0; $i < $c; $i++)
{
$s1 = mb_substr($str1, $i, 1);
$s2 = mb_substr($str2, $i, 1);
if ($s1===$s2) continue;
$i1 = mb_strpos($alphabet, $s1);
if ($i1===false) continue;
$i2 = mb_strpos($alphabet, $s2);
if ($i2===false) continue;
if ($i2===$i1) continue;
if ($i1 < $i2) return -1;
else return 1;
}
if ($l1 < $l2) return -1;
elseif ($l1 > $l2) return 1;
return 0;
}
$names=["Schön","Åsberg","Zierer","Ås","Žižek","Schon","Asber"];
usort($names, 'compare_by_alphabet');
var_dump($names);
结果
array(7) {
[0]=>string(5) "Asber"
[1]=>string(3) "Ås"
[2]=>string(7) "Åsberg"
[3]=>string(5) "Schon"
[4]=>string(6) "Schön"
[5]=>string(6) "Zierer"
[6]=>string(7) "Žižek"
}