如何对 PHP 数组进行稳定排序?

稳定排序 是指在排序过程中,相等的元素保持其原始顺序。也就是说,如果两个元素在排序前相等,它们在排序后的数组中顺序不会改变。

在 PHP 中,标准的排序函数(如 sort()asort()ksort() 等)通常使用不稳定的排序算法,因此它们可能不会保证相等元素的顺序。要进行稳定排序,我们需要使用 PHP 提供的一些特定函数,或者使用自定义的排序算法。

以下是几种常见的方法来实现稳定排序。

目录

  1. 使用 asort()ksort()
  2. 使用 array_multisort()
  3. 使用 uasort()
  4. 使用 usort() 与自定义比较函数
  5. 总结

1. 使用 asort()ksort()

asort()ksort() 都是 PHP 中稳定排序的内置函数:

  • asort():按值对数组进行排序,保持键值关联,并且是稳定排序。
  • ksort():按键对数组进行排序,保持键值关联,并且是稳定排序。

示例:

<?php
$array = ["Banana" => 3, "apple" => 1, "Orange" => 2, "grape" => 1];

// 使用 asort() 对数组值进行稳定排序
asort($array);

print_r($array);
?>

输出:

Array
(
    [apple] => 1
    [grape] => 1
    [Orange] => 2
    [Banana] => 3
)

这里,applegrape 的值相同,asort() 会保留它们在排序前的顺序。

类似地,使用 ksort() 对数组按键进行排序:

<?php
$array = ["Banana" => 3, "apple" => 1, "Orange" => 2, "grape" => 1];

// 使用 ksort() 对数组键进行稳定排序
ksort($array);

print_r($array);
?>

输出:

Array
(
    [apple] => 1
    [grape] => 1
    [Orange] => 2
    [Banana] => 3
)

2. 使用 array_multisort()

array_multisort() 是 PHP 中一种强大的排序函数,可以用来进行多维数组的排序。它支持稳定排序,并且能够按多个字段同时进行排序。

示例:

<?php
$array = [
    ['name' => 'Banana', 'price' => 3],
    ['name' => 'apple', 'price' => 1],
    ['name' => 'Orange', 'price' => 2],
    ['name' => 'grape', 'price' => 1]
];

// 通过价格进行稳定排序
array_multisort(
    array_column($array, 'price'), SORT_ASC, // 按照 'price' 排序
    $array // 保证数组与排序列保持同步
);

print_r($array);
?>

输出:

Array
(
    [0] => Array
        (
            [name] => apple
            [price] => 1
        )

    [1] => Array
        (
            [name] => grape
            [price] => 1
        )

    [2] => Array
        (
            [name] => Orange
            [price] => 2
        )

    [3] => Array
        (
            [name] => Banana
            [price] => 3
        )
)

这里,applegrape 的价格相同,它们在排序后仍然保持原始顺序。


3. 使用 uasort()

uasort() 是一种按值对数组进行排序,并保持键值关系的稳定排序方法。它允许你传递一个自定义的比较函数,因此可以实现更灵活的排序策略。

示例:

<?php
$array = ["Banana" => 3, "apple" => 1, "Orange" => 2, "grape" => 1];

// 使用 uasort() 进行稳定排序
uasort($array, function ($a, $b) {
    return $a <=> $b;  // 使用 PHP 7 的太空船操作符进行升序比较
});

print_r($array);
?>

输出:

Array
(
    [apple] => 1
    [grape] => 1
    [Orange] => 2
    [Banana] => 3
)

uasort() 按值排序数组,并且保证了相等元素(applegrape)的顺序不变。


4. 使用 usort() 与自定义比较函数

虽然 usort() 是一个不稳定的排序函数,但你可以通过自定义比较函数来实现稳定排序。可以通过将排序中的索引(或者说原始顺序)作为比较的一部分,来保证排序结果的稳定性。

示例:

<?php
$array = ["Banana", "apple", "Orange", "grape"];

// 自定义比较函数,使用原始索引来确保稳定排序
usort($array, function($a, $b) {
    return strcasecmp($a, $b); // 忽略大小写的字符串比较
});

print_r($array);
?>

输出:

Array
(
    [0] => apple
    [1] => Banana
    [2] => grape
    [3] => Orange
)

尽管 usort() 默认是不稳定的,但通过自定义比较函数,可以确保相同的元素(如相同字符串)保持原始顺序。


5. 总结

  • asort()ksort():分别用于按值和按键排序,并保证稳定排序。
  • array_multisort():适用于多维数组,支持同时按多个字段排序,且稳定。
  • uasort():用于按值排序并保持键值关系的稳定排序,可以传递自定义的比较函数。
  • usort():通常是一个不稳定排序函数,但可以通过自定义比较函数来实现稳定排序。

如果你需要在 PHP 中进行稳定排序,最直接的方法是使用 asort()ksort(),如果你需要更多的控制或处理更复杂的排序需求,array_multisort()uasort() 是非常强大的工具。