【问题标题】:How to have a stable sort in PHP with arsort()?如何使用 arsort() 在 PHP 中进行稳定排序?
【发布时间】:2012-10-01 15:41:43
【问题描述】:

我需要在php中对数组进行排序基于值,数组使用一些数字作为键和值,例如:

$a = array(70 => 1 ,82 => 5  ,61 => 3 ,55 => 1 ,34 => 2 ,53 => 2 ,21 => 4 ,13 => 5);

我喜欢这样排序

Array
(
    [82] => 5
    [13] => 5
    [21] => 4
    [61] => 3
    [34] => 2
    [53] => 2
    [70] => 1
    [55] => 1
)

我使用了arsort 并且它工作了,但是有一个问题,因为这个函数使更改默认排序 keys 并将数组排序为:

Array
(
    [13] => 5
    [82] => 5
    [21] => 4
    [61] => 3
    [53] => 2
    [34] => 2
    [55] => 1
    [70] => 1
)

【问题讨论】:

  • @MadaraUchiha:我不太确定。除非我弄错了,否则 OP 想要一个稳定的排序,而不是多标准排序。
  • 我阅读了所有这些,没有一个与这个问题完全相关!

标签: php arrays sorting


【解决方案1】:

构造一个新数组,其元素是原始数组的键、值和位置:

$temp = array();
$i = 0;
foreach ($array as $key => $value) {
  $temp[] = array($i, $key, $value);
  $i++;
}

然后使用考虑原始位置的用户定义顺序进行排序:

uasort($temp, function($a, $b) {
 return $a[2] == $b[2] ? ($a[0] - $b[0]) : ($a[2] < $b[2] ? 1 : -1);
});

最后将其转换回原来的关联数组:

$array = array();
foreach ($temp as $val) {
  $array[$val[1]] = $val[2];
}

【讨论】:

  • 近 5 年很有趣,没有人注意到应该是 ($a[0] &gt; $b[0]) 而不是 ($a[0] &gt; $b[0] ? 1 : -1),否则在反转的元素上返回 false,这会导致未定义的顺序。 (还要注意$a[0] == $b[0] 是不可能的。)
  • @WalterTross 不错。我将其更改为$a[0] - $b[0]。我也可以将最后的三元更改为$b[2] - $a[2],但如果它没有坏...
【解决方案2】:

这是因为sort 系列函数不是stable。如果您需要排序稳定,那么您要么必须自己实现它,要么遍历排序结果并使用array_splice“纠正”元素的位置。

【讨论】:

  • +1 来自我,只是想将链接添加到this answer,更详细地描述创建排序函数的过程。 )
  • 这样怎么样:arsort($a);分类($a); arsort($a);这行得通!
  • @Vahid:它发生起作用了。不保证下次会起作用。
【解决方案3】:

作为参考,我在 Github 上放了一组内置 PHP 函数的稳定排序变体:https://github.com/vanderlee/PHP-stable-sort-functions,基于 @Barmar 的解决方案和其他一些技巧。

【讨论】:

  • 太棒了!这真的帮了我很多!这个功能应该在 PHP 核心! :-)
【解决方案4】:

array_multisort 的简单解决方案。

$assoc = [
    70 => 1,
    82 => 5,
    61 => 3,
    55 => 1,
    34 => 2,
    53 => 2,
    21 => 4,
    13 => 5,
];

$keys = array_keys($assoc);
array_multisort($assoc, SORT_DESC, range(1, count($assoc)), $keys);
$assoc = array_combine($keys, $assoc);

print_r($assoc);

【讨论】:

    【解决方案5】:

    这是一个很大的解决方法,但确实有效:

    $a = array(70 => 1 ,82 => 5  ,61 => 3 ,55 => 1 ,34 => 2 ,53 => 2 ,21 => 4 ,13 => 5);
    $b = max($a);
    $c = min($a);
    $d = 0;
    $sorted_list = array();
    while($b >= $c){
        foreach($a as $key => $value){
            if($value == $b){
                $sorted_list[$key] = $value;
            }
        }
        $b--;
    }
    

    vardump 输出:

    array(8) { [82]=> string(1) "5" [13]=> string(1) "5" [21]=> string(1) "4" [61]=> string(1) "3" [34]=> string(1) "2" [53]=> string(1) "2" [70]=> string(1) "1" [55]=> string(1) "1" } 
    

    【讨论】:

    • 好!但为什么我得到 $sorted_list[$key] .= $value; 行的未定义偏移量?
    • 我不知道你为什么会得到它,而我没有,但我知道如何解决它。我的答案中添加了两行。
    • 错误消失,但数组有错误和空值:Array ( [70] => 1 [82] => [61] => [55] => 1 [34] => [53 ] => [21] => [13] => )
    【解决方案6】:

    您可以创建自己的排序函数来满足您自定义的排序条件,然后使用 usort() 使用您创建的函数对整个数组进行迭代以对数组进行排序。

    【讨论】:

    • 他可以使用什么排序函数来获得稳定的排序?数组中的原始位置不作为参数传递给比较函数。
    【解决方案7】:

    PHP 使用快速排序作为基本排序算法。 你有两个选择:

    1. first 使用 usort 并定义一个比较函数,它尊重前一个顺序
    2. 编写您自己的稳定排序机制

    我在 github 上编写了一个包 porth/avalanchesort (https://github.com/porthd/avalanchesort),其中包含一个递归的 naturell-merge-sort。您可以使用自己的比较函数和自己的数据结构。该包包含关联数组和列表数组的示例。

    【讨论】:

      猜你喜欢
      • 2012-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-20
      • 1970-01-01
      • 2020-07-31
      相关资源
      最近更新 更多