在PHP中对特殊字符的数组进行排序

13

我有一个用西班牙语表示编程语言名称的数组:

$lang["ko"] = "coreano"; //korean
$lang["ar"] = "árabe"; //arabic
$lang["es"] = "español"; //spanish
$lang["fr"] = "francés"; //french

我需要对数组进行排序并维护索引关联,因此我使用asort()SORT_LOCALE_STRING参数。

setlocale(LC_ALL,'es_ES.UTF-8'); //this is at the beginning (config file)
asort($lang,SORT_LOCALE_STRING);
print_r($lang);

期望的输出应该是这个顺序:

  • Array ( [ar] => árabe [ko] => coreano [es] => español [fr] => francés )

然而,我收到的却是这个顺序:

  • Array ( [ko] => coreano [es] => español [fr] => francés [ar] => árabe )

我漏了什么吗?感谢您的反馈!(我的服务器正在使用PHP版本5.2.13)


猜测可能是因为 cá 之前吧? - Andreas Wong
这就是为什么我使用SORT_LOCALE_STRING。'á'应该在'a'之后和'c'之前。 - Andres SK
2
你检查了setlocale的返回值吗?很可能它失败了。 - Jon
没错,它很好用。它可以与所有其他区域设置函数(如strftime())一起使用。 - Andres SK
1
@andufo:“it's fine”是什么意思?另外,你用的是哪个操作系统? - Jon
可能是重复的问题:如何在PHP中对带有特殊字符的数组进行排序 - Jacob
5个回答

15

尝试按照转换后的名称进行排序:

function compareASCII($a, $b) {
    $at = iconv('UTF-8', 'ASCII//TRANSLIT', $a);
    $bt = iconv('UTF-8', 'ASCII//TRANSLIT', $b);
    return strcmp($at, $bt);
}

uasort($lang, 'compareASCII');

print_r($lang);

4
这种方法可能对特定情况有效,但不是一个健壮的通用解决方案;如果您想对包含西里尔或希腊字母字符串的数组进行排序会发生什么? ASCII转换并不十分可靠。 - Will Vousden
@WillVousden 你是对的。不管怎样,对于一个包含语言名称的数组来说,我认为这样做没问题。 - lorenzo-s
1
@lorenzo-s:Will是正确的,数组的内容并不影响它(如果它是用希腊语写的语言名称呢?)。这个解决方案可能很有创意,但在技术层面上基本上是有缺陷的。最好还是排除问题,因为原始代码对其他人有效。 - Jon
@lorenzo-s:这可能是可以的,但如果后来决定语言名称应该用其本身的语言(和相应的字母表)表示,例如韩语:“한국의”,那就可能会有问题 :) - Will Vousden
@WillVousden 很好的观点。实际上,同样的代码也适用于中文和希伯来字符。 - Andres SK

3
您在setlocale()中定义了错误的区域设置。
请更改为:
setlocale(LC_ALL,'es_ES.UTF-8');

致:

setlocale(LC_ALL,'es_ES');

输出:

Array ( [ar] => árabe [ko] => coreano [es] => español [fr] => francés ) 

我也尝试了那个,但它返回相同的响应:数组([ko] => 韩语 [es] => 西班牙语 [fr] => 法语 [ar] => 阿拉伯语) - Andres SK
2
如果文件编码为UTF-8,则该区域设置是100%正确的。无论如何,区域设置后缀和文件编码应匹配。 - Jon
@andufo 请尝试在phptester.net上运行它,我在那里测试过了,一切正常。如果是这种情况,您应该能看到Jon的评论并检查您的文件编码方式。 - George Reith
@GeorgeReith 你说得对。我刚在phptester.net上测试了一下,结果很好--你有什么想法,为什么它在我的服务器上不起作用?该文件是UTF-8编码的。 - Andres SK
1
@andufo 太棒了,我建议你在测试服务器上运行 echo mb_internal_encoding(); 以查看你的文件实际编码方式。然后你可以正确设置它,例如 mb_internal_encoding("UTF-8");,如果你使用的是 Apache,那么你的 .htaccess 可能会改变页面所提供的编码方式。 - George Reith
显示剩余3条评论

1

setlocale 的文档提到:

不同的系统对于区域设置有不同的命名方案。

你的系统可能无法识别 es_ES 作为区域设置。如果你使用的是 Windows 系统,可以尝试使用 esp_ESP


0

试试这个

setlocale(LC_COLLATE, 'nl_BE.utf8');
$array = array('coreano','árabe','español','francés');
usort($array, 'strcoll'); 
print_r($array);

0

这不是问题!

您的初始解决方案完全按预期工作,您的问题在于setlocale函数无法设置区域设置,因此asort($array, SORT_LOCALE_STRING)无法按您的期望进行排序。

您可以尝试在phptester.net上使用自己的代码,该网站支持setlocale():

$lang["ko"] = "coreano"; //korean
$lang["ar"] = "árabe"; //arabic
$lang["es"] = "español"; //spanish
$lang["fr"] = "francés"; //french

asort($lang,SORT_LOCALE_STRING);
echo "<pre>";
print_r($lang);
echo "</pre>";

echo "<pre>";
/*this should return es_ES; 
if returns false it has failed and asort wont return expected order
*/
var_dump(setlocale(LC_ALL,'es_ES')); 
echo "</pre>";

asort($lang,SORT_LOCALE_STRING);
echo "<pre>";
print_r($lang);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接