【问题标题】:Trying to sort a multidimensional array, by a sub-value with special characters尝试按带有特殊字符的子值对多维数组进行排序
【发布时间】:2023-03-11 17:53:01
【问题描述】:

我曾经有一个包含国家列表的 PHP 数组:

$countries = array(
  'AX' => 'Åland Islands',
  'AF' => 'Afghanistan',
  'GB' => 'United Kingdom'
);

$collator = collator_create('en');
collator_asort($collator, $countries, Collator::SORT_STRING);

显然这个列表对于这个例子来说要短得多,但是这里的排序是有效的。我期待并得到:

  • 阿富汗
  • 奥兰群岛
  • 英国

但是,我需要添加更多数据,并且它变得多维:

$countries = array(
  array(
    'name' => 'Åland Islands',
    'code' => 'AX'
  ),
  array(
    'name' => 'Afghanistan',
    'code' => 'AF'
  ),
  array(
    'name' => 'United Kingdom',
    'code' => 'GB'
  )
);

usort($countries, function($a, $b){ return $a['name'] <=> $b['name']; });

它对列表中的所有其他国家/地区进行排序,但给了我这个:

  • 阿富汗
  • 英国
  • 奥兰群岛

我一生都无法弄清楚如何正确排序。我意识到在当前状态下没有调用或应用整理器,但是有没有办法让整理器在多维环境中工作?

【问题讨论】:

  • 我应该说,在使用字母 Å 的国家,它通常是字母表中的最后一个,就像在挪威这里是字符号。 29. 在排序时,它通常是 A-Å,所以对我来说,在这样的列表底部查找它是很自然的。

标签: php sorting multidimensional-array collation


【解决方案1】:

要对没有Collator“国家/地区列表” 进行排序,您应该将所有带有重音 字符的单词转换为其ASCII 表示形式(例如Å 到@987654324 @) 通过使用iconv 函数:

usort($countries, function($a, $b){
    return strcasecmp(iconv('utf-8', 'ascii//TRANSLIT', $a['name']), iconv('utf-8', 'ascii//TRANSLIT', $b['name']));    
});

print_r($countries);

输出:

Array
(
    [0] => Array
        (
            [name] => Afghanistan
            [code] => AF
        )

    [1] => Array
        (
            [name] => Åland Islands
            [code] => AX
        )

    [2] => Array
        (
            [name] => United Kingdom
            [code] => GB
        )
)

【讨论】:

  • 有趣的是,这实际上将奥兰群岛放在了我的代码中之前阿富汗。但是,我可以保留 Collat​​or 用于 i18n 目的
【解决方案2】:

以下是基于您的初始方法的可能修复:

usort($countries, function($a, $b) {
  $collator = collator_create('en');
  $arr = array($a['name'], $b['name']);
  collator_asort($collator, $arr, Collator::SORT_STRING);

  return array_pop($arr) == $a['name'];
});

不过,为了在长列表上获得最佳性能,您可能只想在匿名函数范围之外实例化一次 $collat​​or。

【讨论】:

  • 这很好用,并且保留了我热衷于做的 Collat​​or。我已经做了一些快速的性能测试,它似乎根本没有减慢脚本的速度。谢谢!
  • 很高兴它适合您的需求。请注意,这里不需要保留 $arr 的键。所以,你可以把collator_asort()换成collator_sort(),把array_pop($arr) == $a['name'];换成$arr[1] == $a['name'];,应该会快一点。
【解决方案3】:

在多维数组的情况下,我们可以使用collator_compare()函数定义自定义排序函数:

$collator = new Collator('en');
usort($countries, function($a, $b) use ($collator) {
    return $collator->compare($a['name'], $b['name']);
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-26
    • 1970-01-01
    • 2013-02-06
    • 1970-01-01
    • 1970-01-01
    • 2014-01-22
    相关资源
    最近更新 更多