UCA +自然排序

我最近了解到PHP已经通过intl扩展支持Unicode Collat​​ion算法:
$array = array
(
    'al', 'be',
    'Alpha', 'Beta',
    'Álpha', 'Àlpha', 'Älpha',
    'かたかな',
    'img10.png', 'img12.png',
    'img1.png', 'img2.png',
);

if (extension_loaded('intl') === true)
{
    collator_asort(collator_create('root'), $array);
}

Array
(
    [0] => al
    [2] => Alpha
    [4] => Álpha
    [5] => Àlpha
    [6] => Älpha
    [1] => be
    [3] => Beta
    [11] => img1.png
    [9] => img10.png
    [8] => img12.png
    [10] => img2.png
    [7] => かたかな
)
正如您所看到的,即使使用混合大小写字符串,这似乎也能完美运行!到目前为止我遇到的唯一缺点是没有对自然排序的支持,我想知道解决这个问题的最佳方法是什么,这样我就可以合并两个世界中最好的一个。 我试图指定
Collator::SORT_NUMERIC
排序标志,但结果更加混乱:
collator_asort(collator_create('root'), $array, Collator::SORT_NUMERIC);

Array
(
    [8] => img12.png
    [7] => かたかな
    [9] => img10.png
    [10] => img2.png
    [11] => img1.png
    [6] => Älpha
    [5] => Àlpha
    [1] => be
    [2] => Alpha
    [3] => Beta
    [4] => Álpha
    [0] => al
)
但是,如果我只使用
img*.png
值运行相同的测试,我会得到理想的输出:
Array
(
    [3] => img1.png
    [2] => img2.png
    [1] => img10.png
    [0] => img12.png
)
任何人都可以想到一种在添加自然排序功能的同时保留Unicode排序的方法吗?     
已邀请:
在文档中再挖掘一下后,我找到了解决方案:
if (extension_loaded('intl') === true)
{
    if (is_object($collator = collator_create('root')) === true)
    {
        $collator->setAttribute(Collator::NUMERIC_COLLATION, Collator::ON);
        $collator->asort($array);
    }
}
输出:
Array
(
    [0] => al
    [3] => Alpha
    [5] => Álpha
    [6] => Àlpha
    [7] => Älpha
    [1] => be
    [4] => Beta
    [10] => img1.png
    [11] => img2.png
    [8] => img10.png
    [9] => img12.png
    [2] => かたかな
)
    
这很简单。您只需将列表预处理为零填充数字。例如,在此文件名列表中使用支持UCA的ucsort脚本:
% cat /tmp/numfiles
img4.png
img1.png
img2.png
img12.png
img21.png
img10.png
img20.png
img3.png
img22.png
将使用Unicode :: Collat​​e模块的
--preprocess
钩子将数字运行转换为零填充数字,从而产生所需的输出:
% ucsort --preprocess='s/(d+)/sprintf "%020d", $1/ge' /tmp/numfiles
img1.png
img2.png
img3.png
img4.png
img10.png
img12.png
img20.png
img21.png
img22.png
查看您引用的PHP文档,看起来PHP库不支持Perl Unicode :: Collat​​e模块支持的完整UCA定制可能性。事实上,它看起来更像是Perl的Unicode :: Collat​​e :: Locale模块,除了PHP库代码似乎不支持Perl代码所做的继承的排序规则选项。 我想如果所有其他方法都失败了,你可以调用Perl代码来完成所需的工作。     
根据@tchrist的回答,我想出了这个:
function sortIntl($array, $natural = true)
{
    $data = $array;

    if ($natural === true)
    {
        $data = preg_replace_callback('~([0-9]+)~', 'natsortIntl', $data);
    }

    collator_asort(collator_create('root'), $data);

    return array_intersect_key($array, $data);
}

function natsortIntl($number)
{
    return sprintf('%020d', $number);
}
输出:
Array
(
    [0] => 1
    [1] => 100
    [2] => al
    [3] => be
    [4] => Alpha
    [5] => Beta
    [6] => Álpha
    [7] => Àlpha
    [8] => Älpha
    [9] => かたかな
    [10] => img1.png
    [11] => img2.png
    [12] => img10.png
    [13] => img20.png
)
仍然希望有更好的解决方案。     

要回复问题请先登录注册