使用PHP的命令排序时如何保持键顺序(稳定排序)?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (322)

这个问题实际上是从这里的另一个问题中得到启发的,所以我想把它扩大一点。

在PHP中有一个关联数组是否可以对其值进行排序,但是如果值等于保留原始键顺序,则可以使用PHP内置的一个(或多个)排序函数?

下面是我用来测试可能的解决方案的脚本:

<?php
header('Content-type: text/plain');
for($i=0;$i<10;$i++){
    $arr['key-'.$i] = rand(1,5)*10;
}
uasort($arr, function($a, $b){
    // sort condition may go here //
    // Tried: return ($a == $b)?1:($a - $b); //
    // Tried: return $a >= $b; //
});
print_r($arr);
?>

因为键是在原始数组中排序的,所以请不要建议按键排序以恢复原来的顺序。

提问于
用户回答回答于

array_multisort派上用场,只需使用一个有序范围作为第二个数组($order只是暂时的,它用于按其原始顺序排序第一个数组的等效项):

$a = [
  "key-0" => 5,
  "key-99" => 3,
  "key-2" => 3,
  "key-3" => 7
];

$order = range(1,count($a));
array_multisort($a, SORT_ASC, $order, SORT_ASC);

var_dump($a);

输出

array(4) {
  ["key-99"]=>
  int(3)
  ["key-2"]=>
  int(3)
  ["key-0"]=>
  int(5)
  ["key-3"]=>
  int(7)
}

下面是测试脚本的输出:

Array
(
    [key-1] => 10
    [key-4] => 10
    [key-5] => 20
    [key-8] => 20
    [key-6] => 30
    [key-9] => 30
    [key-2] => 40
    [key-0] => 50
    [key-3] => 50
    [key-7] => 50
)

Downside

它只适用于预定义的比较,您不能使用自己的比较函数。array_multisort()的可能值是:

排序类型标志

  • SORT_ASC-优先排序项目。
  • SORT_DESC-逐项排序。
  • SORT_REGULAR-通常比较项目(不要更改类型)
  • SORT_NUMERIC-对项目进行数字比较
  • SORT_STRING-将项目作为字符串进行比较
  • SORT_LOCALE_STRING-根据当前区域设置将项作为字符串进行比较。它使用区域设置,可以使用setlocale()
  • SORT_NATURAL-使用“自然排序”将项目作为字符串进行比较,如natsort()
  • SORT_FLAG_CASE-可以(按位或)合并SORT_STRINGSORT_NATURAL对不敏感字符串进行排序
用户回答回答于

PHP不支持PHP4.1.0之后的稳定排序,您需要编写自己的函数。

<?php
function mergesort(&$array, $cmp_function = 'strcmp') {
    // Arrays of size < 2 require no action.
    if (count($array) < 2) return;
    // Split the array in half
    $halfway = count($array) / 2;
    $array1 = array_slice($array, 0, $halfway);
    $array2 = array_slice($array, $halfway);
    // Recurse to sort the two halves
    mergesort($array1, $cmp_function);
    mergesort($array2, $cmp_function);
    // If all of $array1 is <= all of $array2, just append them.
    if (call_user_func($cmp_function, end($array1), $array2[0]) < 1) {
        $array = array_merge($array1, $array2);
        return;
    }
    // Merge the two sorted arrays into a single sorted array
    $array = array();
    $ptr1 = $ptr2 = 0;
    while ($ptr1 < count($array1) && $ptr2 < count($array2)) {
        if (call_user_func($cmp_function, $array1[$ptr1], $array2[$ptr2]) < 1) {
            $array[] = $array1[$ptr1++];
        }
        else {
            $array[] = $array2[$ptr2++];
        }
    }
    // Merge the remainder
    while ($ptr1 < count($array1)) $array[] = $array1[$ptr1++];
    while ($ptr2 < count($array2)) $array[] = $array2[$ptr2++];
    return;
}
?>

扫码关注云+社区

领取腾讯云代金券