首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用PHP的uasort排序时保留键顺序(稳定排序)

使用PHP的uasort排序时保留键顺序(稳定排序)
EN

Stack Overflow用户
提问于 2010-12-04 21:32:27
回答 7查看 14.6K关注 0票数 24

这个问题实际上是从这里的另一个问题中获得的灵感,所以我想稍微扩展一下。

在PHP中使用一个(或多个)内置排序函数,在PHP中使用一个(或多个)关联数组可以对其值进行排序吗?

以下是我用来测试可能的解决方案的脚本(尚未找到任何解决方案):

代码语言:javascript
复制
<?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);
?>

Pitfall:因为键是在原始数组中排序的,所以请不要试图建议按键排序,以恢复到原始顺序。我在示例中对它们进行了排序,以便更容易直观地检查它们在输出中的顺序。

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2010-12-04 21:58:41

开始,您需要编写自己的函数。

这似乎做了您想做的事情:http://www.php.net/manual/en/function.usort.php#38827

正如手册所说,“如果两个成员进行相等比较,则它们在排序数组中的顺序是未定义的。”这意味着使用的排序不是“稳定的”,并且可能会改变比较相等的元素的顺序。

有时候你真的需要一个稳定的排序。例如,如果您按一个字段对列表进行排序,然后再按另一个字段对其进行排序,但不希望丢失前一个字段的排序。在这种情况下,最好将usort与考虑两个字段的比较函数一起使用,但如果不能这样做,则使用下面的函数。它是一种合并排序,其复杂度保证为O(n*log(n)),这意味着即使您使用较大的列表(与冒泡排序和插入排序不同,它们的复杂度为O(n^2)),它也会保持相当快的速度。

代码语言:javascript
复制
<?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;
}
?>

此外,您还可以找到 interesting.

票数 28
EN

Stack Overflow用户

发布于 2013-02-18 21:07:54

array_multisort很方便,只需使用一个有序的范围作为第二个数组($order只是临时的,它用于按原始顺序对第一个数组的等价项进行排序):

代码语言:javascript
复制
$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);

输出

代码语言:javascript
复制
array(4) {
  ["key-99"]=>
  int(3)
  ["key-2"]=>
  int(3)
  ["key-0"]=>
  int(5)
  ["key-3"]=>
  int(7)
}

我使用带有无序键的测试数据来演示它的工作正常。尽管如此,以下是您的测试脚本的输出:

代码语言:javascript
复制
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
)

不足之处

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

排序类型标志

  • SORT_ASC - sort items ascendingly.
  • SORT_DESC - sort items descendingly.
  • SORT_REGULAR -正常比较项目(不更改types)
  • SORT_NUMERIC - compare items numerically
  • SORT_STRING - compare items as strings
  • SORT_LOCALE_STRING -根据当前语言环境将项目作为字符串进行比较。它使用区域设置,可以使用setlocale()
  • SORT_NATURAL更改区域设置-使用natsort()
  • SORT_FLAG_CASE之类的“自然排序”将项目作为字符串进行比较-可以与SORT_STRINGSORT_NATURAL组合(按位OR)对字符串进行case-insensitively

排序

票数 11
EN

Stack Overflow用户

发布于 2015-05-23 18:25:31

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

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4353739

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档