使用排序规则对数组进行排序
Posted
技术标签:
【中文标题】使用排序规则对数组进行排序【英文标题】:Sorting array with collation 【发布时间】:2012-11-14 07:25:00 【问题描述】:我有一个包含法语单词的数组:['États-Unis', 'Espagne', etc] 我想根据其语言环境 (fr_FR) 按字母顺序排序
我正在使用以下代码:
$collator = new Collator('fr-FR');
echo $collator->getErrorMessage();
$collator->asort($array);
但我收到错误 U_USING_DEFAULT_WARNING 我假设正在使用英语或其他语言环境。更重要的是,数组没有正确排序(美国出现在西班牙之前,我预计会发生相反的情况)
我已经安装了 intl 包,我的系统有相应的语言环境(Ubuntu)
$locale -a
C
C.UTF-8
en_US.utf8
es_ES.utf8
fr_FR
fr_FR.iso88591
fr_FR.utf8
POSIX
我在构造Collation对象的时候尝试了不同的组合,没有任何好的结果:“fr-FR”、“fr-FR.UTF8”等
我还有什么遗漏的吗?
【问题讨论】:
嗯,你试过fr_FR
,对吧?
是的,我也尝试过,但没有成功。顺便说一句,我之前没有设置任何语言环境,我只是使用这个整理器类。我认为这不需要工作,对吧?
不应该。您可以测试 collator_create() 是否会产生任何影响,或检查 Collator::FRENCH_COLLATION
。
是的,我做的最后一件事是更改为 Collator::create() 结果相同。
【参考方案1】:
根据this blog post,对于单词cote、cote、côte和côté(已排序英文),法文排序为:cote、côte、cote和côté。下面的代码对法语排序规则中的单词进行排序:
$words = array('cote', 'coté', 'côte', 'côté');
print_r($words);
$collator = new Collator('fr_FR');
// print info about locale
echo 'French Collation ' . (($collator->getAttribute(Collator::FRENCH_COLLATION) == Collator::ON) ? 'On' : 'Off') . "\n";
echo $collator->getLocale(Locale::VALID_LOCALE) . "\n";
echo $collator->getLocale(Locale::ACTUAL_LOCALE) . "\n";
$collator->asort($words);
print_r($words);
打印出来的结果如下:
Array
(
[0] => cote
[1] => coté
[2] => côte
[3] => côté
)
French Collation On
fr_FR
fr
Array
(
[0] => cote
[2] => côte
[1] => coté
[3] => côté
)
作者在同一篇博文中说:
[...] 变音符号是从右到左而不是从左到右计算的。因此 côte 出现在 coté 之前,而不是像英语这样从左到右评估它们的语言中那样在它之后。因为côte这个词在词尾的“e”上没有ACUTE,而coté有。在英语和大多数其他语言中,评估从左侧开始,因此“o”上的 CIRCUMFLEX 或缺少它是排序的控制因素。
因此,如果您有一个包含 Spain 和 US 字样的数组,它们在英语和法语中的顺序将相同。
您还应该记住asort
方法维护数组的索引关联。看看区别:
asort:
Array
(
[0] => cote
[2] => côte
[1] => coté
[3] => côté
)
sort:
Array
(
[0] => cote
[1] => côte
[2] => coté
[3] => côté
)
关于 U_USING_DEFAULT_WARNING
据此API documentation:
U_USING_DEFAULT_WARNING 表示使用了默认的语言环境数据;既找不到请求的语言环境,也找不到它的任何后备语言环境。
例如,当我使用 fr_FR 语言环境时,我会收到一个 U_USING_FALLBACK_WARNING,这表明使用了备用语言环境,在本例中为语言环境 fr。
语言环境
看起来,您的计算机不支持法语(或者它确实支持,但不知何故 php 无法使用它,然后回退到默认语言),即使命令 locale -a
显示法语包.我有一些建议你可以试试。
首先,列出所有支持的语言环境:
cat /usr/share/i18n/SUPPORTED
现在,生成您需要的语言:
sudo locale-gen fr_FR.UTF-8
sudo locale-gen fr_FR.ISO-8859-1
sudo dpkg-reconfigure locales
如果不起作用,请尝试安装包 language-pack-fr 和 language-support-fr 并重新生成语言。
这个问题很奇怪。我有一个带有 Ubuntu 11.04 和 PHP 5.3.8 的虚拟机,它在我的 Debian 6 中也能正常工作,而且我还没有安装任何软件包或配置任何东西。
【讨论】:
感谢您的回答。我刚刚在我的系统上按原样尝试了您的示例,但我实际遇到的问题是我似乎无法实例化法语整理器。当我尝试您的代码时,我得到:“French Collation Off,fr_FR,root”,即使我的系统中碰巧有法语语言环境(参见原始帖子)。你知道这可能是什么原因吗? 对不起,迟到的答案。我终于解决了完全重新安装的问题。找不到什么不允许我使用语言环境。感谢您的彻底回复。【参考方案2】:我正在使用 cygwin:
$ locale -a | grep fr_FR
fr_FR
fr_FR.utf8
fr_FR@euro
(注意我在输出中没有fr_FR.iso88591
)
代码(文件编码为UTF-8):
$collator = new Collator('fr_FR');
var_dump($collator->getErrorMessage());
// FRENCH_COLLATION is OFF
$arr = array('États-Unis', 'Espagne');
var_dump($collator->getAttribute(Collator::FRENCH_COLLATION) == Collator::ON);
var_dump($collator->getLocale(Locale::VALID_LOCALE));
var_dump($collator->getLocale(Locale::ACTUAL_LOCALE));
$collator->asort($arr);
var_dump($arr);
// FRENCH_COLLATION is ON
$collator->setAttribute(Collator::FRENCH_COLLATION, Collator::ON);
$arr = array('États-Unis', 'Espagne');
var_dump($collator->getAttribute(Collator::FRENCH_COLLATION) == Collator::ON);
var_dump($collator->getLocale(Locale::VALID_LOCALE));
var_dump($collator->getLocale(Locale::ACTUAL_LOCALE));
$collator->asort($arr);
var_dump($arr);
输出:
string(23) "U_USING_DEFAULT_WARNING"
bool(false)
string(5) "fr_FR"
string(4) "root"
array(2)
[1]=>
string(7) "Espagne"
[0]=>
string(11) "États-Unis"
bool(true)
string(5) "fr_FR"
string(4) "root"
array(2)
[1]=>
string(7) "Espagne"
[0]=>
string(11) "États-Unis"
诀窍如下:我将文件编码转换为 ISO 8859-1(在 vim 中,我使用 :set fileencoding=iso-8859-1
)然后再试一次:
string(23) "U_USING_DEFAULT_WARNING"
bool(false)
string(5) "fr_FR"
string(4) "root"
array(2)
[0]=>
string(10) "▒tats-Unis"
[1]=>
string(7) "Espagne"
bool(true)
string(5) "fr_FR"
string(4) "root"
array(2)
[0]=>
string(10) "▒tats-Unis"
[1]=>
string(7) "Espagne"
有些符号坏了,但我认为这是因为我的终端不支持给定的代码页。主要的是,现在字符串的顺序正是您所描述的:“Espagne”在“États-Unis”之后。
所以,我认为这是一种文件编码。
【讨论】:
【参考方案3】:试试 'FR',我猜它应该适用于你的系统:
$collator = new Collator('FR');
【讨论】:
以上是关于使用排序规则对数组进行排序的主要内容,如果未能解决你的问题,请参考以下文章