如何在 PHP 中对数组和数据进行排序?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17364127/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 12:44:31  来源:igfitidea点击:

How can I sort arrays and data in PHP?

phparrayssortingobjectspl

提问by deceze

This question is intended as a reference for questions about sorting arrays in PHP. It is easy to think that your particular case is unique and worthy of a new question, but most are actually minor variations of one of the solutions on this page.

If your question is closed as a duplicate of this one, please ask for your question to be reopened only if you can explain why it differs markedly from all of the below.

此问题旨在作为有关在 PHP 中对数组进行排序的问题的参考。很容易认为您的特定案例是独一无二的,值得提出一个新问题,但大多数实际上是此页面上一个解决方案的微小变化。

如果您的问题作为此问题的副本而关闭,请仅在您能解释为什么它与以下所有问题明显不同的情况下才要求重新打开您的问题。

How do I sort an array in PHP?
How do I sort a complexarray in PHP?
How do I sort an array of objects in PHP?

如何在 PHP 中对数组进行排序?
如何在 PHP 中对复杂数组进行排序?
如何在 PHP 中对对象数组进行排序?



  1. Basic one-dimensional arrays; Incl. Multidimensional arrays, incl. arrays of objects; Incl. Sorting one array based on another

  2. Sorting with SPL

  3. Stable sort

  1. 基本的一维数组;包括 多维数组,包括 对象数组;包括 根据另一个数组对一个数组进行排序

  2. 使用 SPL 排序

  3. 稳定排序

For the practical answer using PHP's existing functions see 1., for the academic in-detail answer on sorting algorithms (which PHP's functions implement and which you mayneed for really, really complex cases), see 2.

有关使用 PHP 现有函数的实际答案,请参阅 1.,有关排序算法的学术详细答案(PHP 的函数实现以及您在非常非常复杂的情况下可能需要哪些),请参阅 2。

采纳答案by deceze

Basic one dimensional arrays

基本的一维数组

$array = array(3, 5, 2, 8);

Applicable sort functions:

适用的排序函数:

  • sort
  • rsort
  • asort
  • arsort
  • natsort
  • natcasesort
  • ksort
  • krsort
  • sort
  • rsort
  • asort
  • arsort
  • natsort
  • natcasesort
  • ksort
  • krsort

The difference between those is merely whether key-value associations are kept (the "a" functions), whether it sorts low-to-high or reverse ("r"), whether it sorts values or keys ("k") and how it compares values ("nat" vs. normal). See http://php.net/manual/en/array.sorting.phpfor an overview and links to further details.

它们之间的区别仅在于是否保留键值关联(“ a”函数),是从低到高排序还是反向r排序(“ ”),是否对值或键进行排序(“ k”)以及它如何比较值(" nat" vs. 正常)。有关概述和更多详细信息的链接,请参阅http://php.net/manual/en/array.sorting.php

Multi dimensional arrays, including arrays of objects

多维数组,包括对象数组

$array = array(
    array('foo' => 'bar', 'baz' => 42),
    array('foo' => ...,   'baz' => ...),
    ...
);

If you want to sort $arrayby the key 'foo' of each entry, you need a custom comparison function. The above sortand related functions work on simple values that they know how to compare and sort. PHP does not simply "know" what to do with a complex valuelike array('foo' => 'bar', 'baz' => 42)though; so you need to tell it.

如果要按$array每个条目的键 'foo'进行排序,则需要自定义比较函数。上述sort和相关函数处理简单的值,它们知道如何比较和排序。PHP 并不简单地“知道”如何处理复杂的值,例如array('foo' => 'bar', 'baz' => 42);所以你需要告诉它。

To do that, you need to create a comparison function. That function takes two elements and must return 0if these elements are considered equal, a value lower than 0if the first value is lower and a value higher than 0if the first value is higher. That's all that's needed:

为此,您需要创建一个比较函数。该函数接受两个元素,并且0如果这些元素被认为相等,则必须返回一个低于0第一个值时的值和一个高于0第一个值时的值。这就是所需要的:

function cmp(array $a, array $b) {
    if ($a['foo'] < $b['foo']) {
        return -1;
    } else if ($a['foo'] > $b['foo']) {
        return 1;
    } else {
        return 0;
    }
}

Often, you will want to use an anonymous functionas the callback. If you want to use a method or static method, see the other ways of specifying a callback in PHP.

通常,您会希望使用匿名函数作为回调。如果要使用方法或静态方法,请参阅PHP 中指定回调其他方法

You then use one of these functions:

然后,您可以使用以下功能之一:

Again, they only differ in whether they keep key-value associations and sort by values or keys. Read their documentation for details.

同样,它们的区别仅在于它们是否保持键值关联并按值或键排序。有关详细信息,请阅读他们的文档。

Example usage:

用法示例:

usort($array, 'cmp');

usortwill take two items from the array and call your cmpfunction with them. So cmp()will be called with $aas array('foo' => 'bar', 'baz' => 42)and $bas another array('foo' => ..., 'baz' => ...). The function then returns to usortwhich of the values was larger or whether they were equal. usortrepeats this process passing different values for $aand $buntil the array is sorted. The cmpfunction will be called many times, at leastas many times as there are values in $array, with different combinations of values for $aand $bevery time.

usort将从数组中取出两个项目并cmp用它们调用您的函数。Socmp()将用$aasarray('foo' => 'bar', 'baz' => 42)$bas another调用array('foo' => ..., 'baz' => ...)。然后该函数返回usort哪个值更大或它们是否相等。usort重复这个过程,为$a和传递不同的值,$b直到数组被排序。该cmp函数将被调用很多次,至少多次,有价值观$array,与值的不同组合$a$b每一次。

To get used to this idea, try this:

要习惯这个想法,试试这个:

function cmp($a, $b) {
    echo 'cmp called with $a:', PHP_EOL;
    var_dump($a);
    echo 'and $b:', PHP_EOL;
    var_dump($b);
}

All you did was define a custom way to compare two items, that's all you need. That works with all sorts of values.

您所做的只是定义一种自定义方式来比较两个项目,这就是您所需要的。这适用于各种值。

By the way, this works on any value, the values don't have to be complex arrays. If you have a custom comparison you want to do, you can do it on a simple array of numbers too.

顺便说一下,这适用于任何值,这些值不必是复杂的数组。如果您想要进行自定义比较,也可以对简单的数字数组进行比较。

sortsorts by reference and does not return anything useful!

sort按引用排序,不返回任何有用的东西!

Note that the array sorts in place, you do not need to assign the return value to anything. $array = sort($array)will replace the array with true, not with a sorted array. Just sort($array);works.

请注意,数组就地排序,您无需将返回值分配给任何内容。$array = sort($array)将用 代替数组true,而不是用已排序的数组。只是sort($array);工作。

Custom numeric comparisons

自定义数字比较

If you want to sort by the bazkey, which is numeric, all you need to do is:

如果您想按baz数字键排序,您需要做的就是:

function cmp(array $a, array $b) {
    return $a['baz'] - $b['baz'];
}

Thanks to The PoWEr oF MATHthis returns a value < 0, 0 or > 0 depending on whether $ais lower than, equal to or larger than $b.

多亏了数学的力量,这会返回一个 < 0、0 或 > 0 的值,具体取决于$a是小于、等于还是大于$b

Note that this won't work well for floatvalues, since they'll be reduced to an intand lose precision. Use explicit -1, 0and 1return values instead.

请注意,这不适用于float值,因为它们将减少为 anint并失去精度。使用显式-101而是返回值。

Objects

对象

If you have an array of objects, it works the same way:

如果你有一个对象数组,它的工作方式是一样的:

function cmp($a, $b) {
    return $a->baz - $b->baz;
}

Functions

职能

You can do anything you need inside a comparison function, including calling functions:

您可以在比较函数中执行任何您需要的操作,包括调用函数:

function cmp(array $a, array $b) {
    return someFunction($a['baz']) - someFunction($b['baz']);
}

Strings

字符串

A shortcut for the first string comparison version:

第一个字符串比较版本的快捷方式:

function cmp(array $a, array $b) {
    return strcmp($a['foo'], $b['foo']);
}

strcmpdoes exactly what's expected of cmphere, it returns -1, 0or 1.

strcmp完全符合cmp这里的预期,它返回-1,01

Spaceship operator

飞船操作员

PHP 7 introduced the spaceship operator, which unifies and simplifies equal/smaller/larger than comparisons across types:

PHP 7 引入了spaceship operator,它统一并简化了相等/更小/大于类型之间的比较:

function cmp(array $a, array $b) {
    return $a['foo'] <=> $b['foo'];
}

Sorting by multiple fields

按多个字段排序

If you want to sort primarily by foo, but if foois equal for two elements sort by baz:

如果您想主要按 排序foo,但如果foo两个元素相等,则按 排序baz

function cmp(array $a, array $b) {
    if (($cmp = strcmp($a['foo'], $b['foo'])) !== 0) {
        return $cmp;
    } else {
        return $a['baz'] - $b['baz'];
    }
}

For those familiar, this is equivalent to an SQL query with ORDER BY foo, baz.
Also see this very neat shorthand versionand how to create such a comparison function dynamically for an arbitrary number of keys.

对于那些熟悉的人来说,这相当于带有ORDER BY foo, baz.
另请参阅这个非常简洁的速记版本以及如何为任意数量的键动态创建这样的比较函数

Sorting into a manual, static order

排序为手动的静态顺序

If you want to sort elements into a "manual order" like "foo", "bar", "baz":

如果要将元素排序为“手动顺序”,例如"foo", "bar", "baz"

function cmp(array $a, array $b) {
    static $order = array('foo', 'bar', 'baz');
    return array_search($a['foo'], $order) - array_search($b['foo'], $order);
}


For all the above, if you're using PHP 5.3 or higher (and you really should), use anonymous functions for shorter code and to avoid having another global function floating around:

对于上述所有内容,如果您使用的是 PHP 5.3 或更高版本(您确实应该),请使用匿名函数来编写更短的代码,并避免出现另一个全局函数:

usort($array, function (array $a, array $b) { return $a['baz'] - $b['baz']; });

That's how simple sorting a complex multi-dimensional array can be. Again, just think in terms of teaching PHP how to tell which of two items is "greater"; let PHP do the actual sorting.

这就是对复杂的多维数组进行排序的简单程度。再一次,想想教 PHP 如何判断两个项目中的哪一个“更大”;让 PHP 进行实际的排序。

Also for all of the above, to switch between ascending and descending order simply swap the $aand $barguments around. E.g.:

同样对于上述所有内容,要在升序和降序之间切换,只需交换$a$b参数。例如:

return $a['baz'] - $b['baz']; // ascending
return $b['baz'] - $a['baz']; // descending

Sorting one array based on another

根据另一个数组对一个数组进行排序

And then there's the peculiar array_multisort, which lets you sort one array based on another:

然后是特殊的array_multisort,它可以让您根据另一个数组对一个数组进行排序:

$array1 = array( 4,   6,   1);
$array2 = array('a', 'b', 'c');

The expected result here would be:

这里的预期结果是:

$array2 = array('c', 'a', 'b');  // the sorted order of $array1

Use array_multisortto get there:

使用array_multisort到那里:

array_multisort($array1, $array2);

As of PHP 5.5.0 you can use array_columnto extract a column from a multi dimensional array and sort the array on that column:

从 PHP 5.5.0 开始,您可以使用array_column从多维数组中提取列并在该列上对数组进行排序:

array_multisort(array_column($array, 'foo'), SORT_DESC, $array);

As of PHP 7.0.0 you can also extract properties from an array of objects.

从 PHP 7.0.0 开始,您还可以从对象数组中提取属性。



If you have more common cases, feel free to edit this answer.

如果您有更常见的情况,请随时编辑此答案。

回答by Baba

Well most basic methods are already covered by decezeI would try to look at other types of sort

好吧,deceze已经涵盖了大多数基本方法,我会尝试查看其他类型的排序

Sorting with SPL

使用 SPL 排序

SplHeap

SplHeap

class SimpleHeapSort extends SplHeap {
    public function compare($a, $b) {
        return strcmp($a, $b);
    }
}

// Let's populate our heap here (data of 2009)
$heap = new SimpleHeapSort();
$heap->insert("a");
$heap->insert("b");
$heap->insert("c");

echo implode(PHP_EOL, iterator_to_array($heap));

Output

输出

c
b
a

SplMaxHeap

SplMaxHeap

The SplMaxHeap class provides the main functionalities of a heap, keeping the maximum on the top.

SplMaxHeap 类提供堆的主要功能,将最大值保持在顶部。

$heap = new SplMaxHeap();
$heap->insert(1);
$heap->insert(2);
$heap->insert(3);

SplMinHeap

SplMinHeap

The SplMinHeap class provides the main functionalities of a heap, keeping the minimum on the top.

SplMinHeap 类提供堆的主要功能,将最小值保留在顶部。

$heap = new SplMinHeap ();
$heap->insert(3);
$heap->insert(1);
$heap->insert(2);

Other Types of Sort

其他类型的排序

Bubble Sort

冒泡排序

From the Wikipedia article on Bubble Sort:

来自维基百科关于冒泡排序的文章:

Bubble sort, sometimes incorrectly referred to as sinking sort, is a simple sorting algorithm that works by repeatedly stepping through the list to be sorted, comparing each pair of adjacent items and swapping them if they are in the wrong order. The pass through the list is repeated until no swaps are needed, which indicates that the list is sorted. The algorithm gets its name from the way smaller elements "bubble" to the top of the list. Because it only uses comparisons to operate on elements, it is a comparison sort. Although the algorithm is simple, most of the other sorting algorithms are more efficient for large lists.

冒泡排序,有时被错误地称为下沉排序,是一种简单的排序算法,它通过重复遍历要排序的列表、比较每对相邻项并在它们的顺序错误时交换它们来工作。重复遍历列表直到不需要交换,这表明列表已排序。该算法的名字来源于较小元素“冒泡”到列表顶部的方式。因为它只使用比较对元素进行操作,所以它是一种比较排序。虽然算法很简单,但大多数其他排序算法对于大列表更有效。

function bubbleSort(array $array) {
    $array_size = count($array);
    for($i = 0; $i < $array_size; $i ++) {
        for($j = 0; $j < $array_size; $j ++) {
            if ($array[$i] < $array[$j]) {
                $tem = $array[$i];
                $array[$i] = $array[$j];
                $array[$j] = $tem;
            }
        }
    }
    return $array;
}

Selection sort

选择排序

From the Wikipedia article on Selection sort:

来自维基百科关于选择排序的文章:

In computer science, selection sort is a sorting algorithm, specifically an in-place comparison sort. It has O(n2) time complexity, making it inefficient on large lists, and generally performs worse than the similar insertion sort. Selection sort is noted for its simplicity, and it has performance advantages over more complicated algorithms in certain situations, particularly where auxiliary memory is limited.

在计算机科学中,选择排序是一种排序算法,特别是就地比较排序。它的时间复杂度为 O(n2),使其在大型列表上效率低下,并且通常比类似的插入排序表现更差。选择排序以其简单性而著称,并且在某些情况下比更复杂的算法具有性能优势,特别是在辅助内存有限的情况下。

function selectionSort(array $array) {
    $length = count($array);
    for($i = 0; $i < $length; $i ++) {
        $min = $i;
        for($j = $i + 1; $j < $length; $j ++) {
            if ($array[$j] < $array[$min]) {
                $min = $j;
            }
        }
        $tmp = $array[$min];
        $array[$min] = $array[$i];
        $array[$i] = $tmp;
    }
    return $array;
}

Insertion sort

插入排序

From the Wikipedia article on Insertion sort:

来自维基百科关于插入排序的文章:

Insertion sort is a simple sorting algorithm that builds the final sorted array (or list) one item at a time. It is much less efficient on large lists than more advanced algorithms such as quicksort, heapsort, or merge sort. However, insertion sort provides several advantages:

插入排序是一种简单的排序算法,它一次构建一个最终排序的数组(或列表)。与更高级的算法(如快速排序、堆排序或归并排序)相比,它在大型列表上的效率要低得多。然而,插入排序提供了几个优点:

function insertionSort(array $array) {
    $count = count($array);
    for($i = 1; $i < $count; $i ++) {

        $j = $i - 1;
        // second element of the array
        $element = $array[$i];
        while ( $j >= 0 && $array[$j] > $element ) {
            $array[$j + 1] = $array[$j];
            $array[$j] = $element;
            $j = $j - 1;
        }
    }
    return $array;
}

Shellsort

贝壳类

From the Wikipedia article on Shellsort:

来自维基百科关于 Shellsort 的文章:

Shellsort, also known as Shell sort or Shell's method, is an in-place comparison sort. It generalizes an exchanging sort, such as insertion or bubble sort, by starting the comparison and exchange of elements with elements that are far apart before finishing with neighboring elements.

Shellsort,也称为Shell sort或Shell's method,是一种就地比较排序。它概括了交换排序,例如插入排序或冒泡排序,在结束与相邻元素之前,先将元素与相距很远的元素进行比较和交换。

function shellSort(array $array) {
    $gaps = array(
            1,
            2,
            3,
            4,
            6
    );
    $gap = array_pop($gaps);
    $length = count($array);
    while ( $gap > 0 ) {
        for($i = $gap; $i < $length; $i ++) {
            $tmp = $array[$i];
            $j = $i;
            while ( $j >= $gap && $array[$j - $gap] > $tmp ) {
                $array[$j] = $array[$j - $gap];
                $j -= $gap;
            }
            $array[$j] = $tmp;
        }
        $gap = array_pop($gaps);
    }
    return $array;
}

Comb sort

梳状排序

From the Wikipedia article on Comb sort:

来自维基百科关于梳子排序的文章:

Comb sort is a relatively simple sorting algorithm originally designed by Wlodzimierz Dobosiewicz in 1980. Later it was rediscovered by Stephen Lacey and Richard Box in 1991. Comb sort improves on bubble sort.

梳状排序是一种比较简单的排序算法,最初由 Wlodzimierz Dobosiewicz 于 1980 年设计,后来在 1991 年被 Stephen Lacey 和 Richard Box 重新发现。梳状排序是对冒泡排序的改进。

function combSort(array $array) {
    $gap = count($array);
    $swap = true;
    while ( $gap > 1 || $swap ) {
        if ($gap > 1)
            $gap /= 1.25;
        $swap = false;
        $i = 0;
        while ( $i + $gap < count($array) ) {
            if ($array[$i] > $array[$i + $gap]) {
                // swapping the elements.
                list($array[$i], $array[$i + $gap]) = array(
                        $array[$i + $gap],
                        $array[$i]
                );
                $swap = true;
            }
            $i ++;
        }
    }
    return $array;
}

Merge sort

归并排序

From the Wikipedia article on Merge sort:

来自维基百科关于合并排序的文章:

In computer science, a merge sort (also commonly spelled mergesort) is an O(n log n) comparison-based sorting algorithm. Most implementations produce a stable sort, which means that the implementation preserves the input order of equal elements in the sorted output

在计算机科学中,归并排序(通常也拼写为归并排序)是一种基于 O(n log n) 比较的排序算法。大多数实现产生稳定的排序,这意味着实现保留排序输出中相等元素的输入顺序

function mergeSort(array $array) {
    if (count($array) <= 1)
        return $array;

    $left = mergeSort(array_splice($array, floor(count($array) / 2)));
    $right = mergeSort($array);

    $result = array();

    while ( count($left) > 0 && count($right) > 0 ) {
        if ($left[0] <= $right[0]) {
            array_push($result, array_shift($left));
        } else {
            array_push($result, array_shift($right));
        }
    }
    while ( count($left) > 0 )
        array_push($result, array_shift($left));

    while ( count($right) > 0 )
        array_push($result, array_shift($right));

    return $result;
}

Quicksort

快速排序

From the Wikipedia article on Quicksort:

来自维基百科关于 Quicksort 的文章:

Quicksort, or partition-exchange sort, is a sorting algorithm developed by Tony Hoare that, on average, makes O(n log n) comparisons to sort n items. In the worst case, it makes O(n2) comparisons, though this behavior is rare.

快速排序或分区交换排序是由 Tony Hoare 开发的一种排序算法,平均而言,对 n 个项目进行 O(n log n) 次比较。在最坏的情况下,它进行 O(n2) 次比较,尽管这种行为很少见。

function quickSort(array $array) {
    if (count($array) == 0) {
        return $array;
    }
    $pivot = $array[0];
    $left = $right = array();
    for($i = 1; $i < count($array); $i ++) {
        if ($array[$i] < $pivot) {
            $left[] = $array[$i];
        } else {
            $right[] = $array[$i];
        }
    }
    return array_merge(quickSort($left), array(
            $pivot
    ), quickSort($right));
}

Permutation sort

排列排序

From the Wikipedia article on Permutation sort:

来自维基百科关于排列排序的文章:

Permutation sort, which proceeds by generating the possible permutations of the input array/list until discovering the sorted one.

排列排序,它通过生成输入数组/列表的可能排列来继续,直到发现已排序的排列。

function permutationSort($items, $perms = array()) {
    if (empty($items)) {
        if (inOrder($perms)) {
            return $perms;
        }
    } else {
        for($i = count($items) - 1; $i >= 0; -- $i) {
            $newitems = $items;
            $newperms = $perms;
            list($foo) = array_splice($newitems, $i, 1);
            array_unshift($newperms, $foo);
            $res = permutationSort($newitems, $newperms);
            if ($res) {
                return $res;
            }
        }
    }
}

function inOrder($array) {
    for($i = 0; $i < count($array); $i ++) {
        if (isset($array[$i + 1])) {
            if ($array[$i] > $array[$i + 1]) {
                return False;
            }
        }
    }
    return True;
}

Radix sort

基数排序

From the Wikipedia article on Radix sort:

来自维基百科关于基数排序的文章:

In computer science, radix sort is a non-comparative integer sorting algorithm that sorts data with integer keys by grouping keys by the individual digits which share the same significant position and value.

在计算机科学中,基数排序是一种非比较整数排序算法,它通过按具有相同重要位置和值的单个数字对键进行分组来对具有整数键的数据进行排序。

// Radix Sort for 0 to 256
function radixSort($array) {
    $n = count($array);
    $partition = array();

    for($slot = 0; $slot < 256; ++ $slot) {
        $partition[] = array();
    }

    for($i = 0; $i < $n; ++ $i) {
        $partition[$array[$i]->age & 0xFF][] = &$array[$i];
    }

    $i = 0;

    for($slot = 0; $slot < 256; ++ $slot) {
        for($j = 0, $n = count($partition[$slot]); $j < $n; ++ $j) {
            $array[$i ++] = &$partition[$slot][$j];
        }
    }
    return $array;
}

回答by Ja?ck

Stable sort

稳定排序

Let's say you have an array like this:

假设你有一个这样的数组:

['Kale', 'Kaleidoscope', 'Aardvark', 'Apple', 'Leicester', 'Lovely']

And now you want to sort on the first letter only:

现在您只想对第一个字母进行排序:

usort($array, function($a, $b) {
    return strcmp($a[0], $b[0]);
});

The outcome is this:

结果是这样的:

['Apple', 'Aardvark', 'Kale', 'Kaleidoscope', 'Lovely', 'Leicester']

The sort wasn't stable!

排序不稳定!

The keen observer may have noticed that the array sorting algorithm (QuickSort) didn't produce a stable outcome and that the original order between words of the same first letter wasn't preserved. This case is trivial and we should have compared the whole string, but let's assume your use-case is more complicated, such as two consecutive sorts on different fields that shouldn't cancel out each other's work.

敏锐的观察者可能已经注意到,数组排序算法 (QuickSort) 没有产生稳定的结果,并且没有保留相同第一个字母的单词之间的原始顺序。这种情况是微不足道的,我们应该比较整个字符串,但让我们假设您的用例更复杂,例如不同字段上的两个连续排序不应相互抵消彼此的工作。

The Schwartzian transform

施瓦兹变换

The Schwartzian transform, also referred to as the decorate-sort-undecorate idiom, effects a stable sort with an inherently unstable sorting algorithm.

Schwartzian 变换,也称为装饰-排序-取消装饰习语,通过固有的不稳定排序算法实现稳定排序。

First, you decorate each array element with another array comprising a primary key (the value) and a secondary key (its index or position):

首先,您用另一个包含主键(值)和辅助键(其索引或位置)的数组装饰每个数组元素:

array_walk($array, function(&$element, $index) {
    $element = array($element, $index); // decorate
});

This transforms the array into this:

这会将数组转换为:

[
    ['Kale', 0], ['Kaleidoscope', 1], 
    ['Aardvark', 2], ['Apple', 3], 
    ['Leicester', 4], ['Lovely', 5]
]

Now, we adjust the comparison step; we compare the first letter again, but if they're the same, the secondary key is used to retain the original ordering:

现在,我们调整比较步骤;我们再次比较第一个字母,但如果它们相同,则使用辅助键保留原始顺序:

usort($array, function($a, $b) {
    // $a[0] and $b[0] contain the primary sort key
    // $a[1] and $b[1] contain the secondary sort key
    $tmp = strcmp($a[0][0], $b[0][0]);

    if ($tmp != 0) {
        return $tmp; // use primary key comparison results
    }

    return $a[1] - $b[1]; // use secondary key
});

Afterwards, we undecorate:

之后,我们取消装饰:

array_walk($array, function(&$element) {
    $element = $element[0];
});

The final result:

最终结果:

['Aardvark', 'Apple', 'Kale', 'Kaleidoscope', 'Leicester', 'Lovely']

What about reuse?

再利用呢?

You had to rewrite your comparison function to work with the transformed array elements; you may not want to edit your delicate comparison functions, so here's a wrapper for the comparison function:

您必须重写比较函数才能处理转换后的数组元素;您可能不想编辑精细的比较函数,因此这里是比较函数的包装器:

function stablecmp($fn)
{
    return function($a, $b) use ($fn) {
        if (($tmp = call_user_func($fn, $a[0], $b[0])) != 0) {
            return $tmp;
        } else {
            return $a[1] - $b[1];
        }
    };
}

Let's write the sort step using this function:

让我们使用此函数编写排序步骤:

usort($array, stablecmp(function($a, $b) {
    return strcmp($a[0], $b[0]);
}));

Voila! Your pristine comparison code is back.

瞧!您的原始比较代码又回来了。

回答by Orangepill

As of PHP 5.3 with closures it is also possible to use a closure to determine the order of your sort.

从带有闭包的 PHP 5.3 开始,还可以使用闭包来确定排序的顺序。

For example assuming $array is an array of objects that contain a month property.

例如,假设 $array 是一个包含月份属性的对象数组。

 $orderArray = array("Jan","Feb","Mar","Apr","May","June","July","Aug","Sept","Oct","Nov","Dec");

 usort($array, function($a, $b) use ($orderArray){
       return array_search($a->month, $orderArray) - array_search($b->month, $orderArray);
 }); 

回答by Athari

LINQ

LINQ

In .NET, LINQ is frequently used for sorting, which provides a much nicer syntax over comparison functions, especially when objects need to be sorted by multiple fields. There're several ports of LINQ to PHP, including YaLinqolibrary*. With it, arrays can be sorted with a single line without writing complex comparison functions.

在 .NET 中,LINQ 经常用于排序,它提供了比比较函数更好的语法,尤其是当对象需要按多个字段排序时。LINQ to PHP 有多个端口,包括YaLinqo库*。有了它,可以用一行对数组进行排序,而无需编写复杂的比较函数。

$sortedByName         = from($objects)->orderBy('$v->name');
$sortedByCount        = from($objects)->orderBy('$v->count');
$sortedByCountAndName = from($objects)->orderBy('$v->count')->thenBy('$v->name');

Comparisons can be further customized by passing a callback as a second argument, for example:

通过将回调作为第二个参数传递,可以进一步自定义比较,例如:

$sortedByFilenameNat  = from($objects)->orderBy('$v->filename', 'strnatcmp');

Here, '$v->count'is a shorthand for function ($v) { return $v->count; }(either can be used). These method chains return iterators, iterators can be transformed to arrays by adding ->toArray()in the end if needed.

在这里,'$v->count'function ($v) { return $v->count; }(两者都可以使用)的简写。这些方法链返回迭代器,->toArray()如果需要,迭代器可以通过在最后添加来转换为数组。

Internally, orderByand related methods call appropriate array sorting functions (uasort, krsort, multisort, usortetc.).

在内部,orderBy以及相关的方法调用相应的数组排序功能(uasortkrsortmultisortusort等等)。

LINQ contains many more methods inspired by SQL: filtering, grouping, joining, aggregating etc. It's best suited for cases when complex transformations on arrays and objects need to be performed without relying on databases.

LINQ 包含更多受 SQL 启发的方法:过滤、分组、连接、聚合等。它最适合需要在不依赖数据库的情况下对数组和对象执行复杂转换的情况。

* developed by me, see readme for more details and comparison with other LINQ ports

* 由我开发,更多细节和与其他 LINQ 端口的比较请参见自述文件

回答by Andrew Surdu

Multidimensional sort by key value

按键值多维排序

Natural sort of a multidimensional array by a key value and also keep the original order(do not shuffle the main keys):

按键值对多维数组进行自然排序并保持原始顺序(不要打乱主键):

function multisortByKeyValue( $k, $arr ) {
    $ids   = array();
    $index = 1;

    foreach ( $arr as $key => $row ) {
        $ids[ $key ] = intval( $row[ $k ] ) . '-' . $index . '-' . $key;
        $index ++;
    }

    natsort( $ids );

    $arr = array_merge( $ids, $arr );

    return $arr;
}

Test case:

测试用例:

$arr = array(
    'id1' => array(
        'label'    => 'ID 1',
        'priority' => 30,
    ),
    'id2' => array(
        'label'    => 'ID 2',
        'priority' => 70,
    ),
    'id3' => array(
        'label'    => 'ID 3',
        'priority' => 20,
    ),
    'id4' => array(
        'label'    => 'ID 4',
        'priority' => 30,
    ),
);

$sorted = multisortByKeyValue( 'priority', $arr );

// $sorted equals to:
/*
array (
  'id3' => array (
    'label' => 'ID 3',
    'priority' => 20,
  ),
  'id1' => array (
    'label' => 'ID 1',
    'priority' => 30,
  ),
  'id4' => array (
    'label' => 'ID 4',
    'priority' => 30,
  ),
  'id2' => array (
    'label' => 'ID 2',
    'priority' => 70,
  ),
)
*/

回答by GAV

If you want to order by the key value, then you can do it one line, elegant and clear. This will order by the price ascending. Uses array_multisort and array_column.

如果要按键值排序,那么一行就可以搞定,优雅清晰。这将按价格升序排列。使用 array_multisort 和 array_column。

   Array([0] => Array ( [name] => eggs [price] => 1 ) [1] => Array ( [name] => coffee [price] => 9.99 ) [2] => Array ( [name] => rice [price] => 4.04 ) )

   array_multisort (array_column($array, 'price'), SORT_ASC, $array);

to produce

生产

     Array ( [0] => Array ( [name] => eggs [price] => 1 ) [1] => Array ( [name] => rice [price] => 4.04 ) [2] => Array ( [name] => coffee [price] => 9.99 ) )

回答by Ihor Burlachenko

It is very convenient to sort arrays with sortedfunction from Nspl:

使用Nspl 中的sorted函数对数组进行排序非常方便:

Basic sorting

基本排序

// Sort array
$sorted = sorted([3, 1, 2]);

// Sort array in descending order
$sortedDesc = sorted([3, 1, 2], true);

Sorting by function result

按功能结果排序

// Sort array by the result of a given function (order words by length)
$sortedByLength = sorted(['bc', 'a', 'abc'], 'strlen');
$sortedByLengthDesc = sorted(['bc', 'a', 'abc'], true, 'strlen');

// Sort array by the result of user-defined function (order words by the 1st character)
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], function($v) { return $v[0]; }); 

// Which is the same as
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], itemGetter(0));
$sortedByTheFirstCharacterDesc = sorted(['bc', 'a', 'abc'], true, itemGetter(0));

// itemGetter(0) returns a function which takes an argument with access by index/key
// and returns the value at index 0

Sorting multidimensional array

多维数组排序

// Sort multidimensional array (sort list of users by their names)
$users = [
    array('name' => 'Robert', 'age' => 20),
    array('name' => 'Alex', 'age' => 30),
    array('name' => 'Hyman', 'age' => 25),
];
$sortedByName = sorted($users, itemGetter('name'));
$sortedByNameDesc = sorted($users, true, itemGetter('name'));

// itemGetter('name') returns a function which takes an argument with access by index/key
// and returns the value of the 'name' key

Sorting array of objects

对象数组排序

// Lets assume we have class User(name, age) with properties name and age
// and public methods getName() and getAge()
$users = [
    new User('Robert', 20),
    new User('Alex', 30),
    new User('Hyman', 25),
];

// Sort list of objects by property value (sort list of users by their name)
$sortedByName = sorted($users, propertyGetter('name'));
$sortedByNameDesc = sorted($users, true, propertyGetter('name'));

// propertyGetter('name') returns a function which takes an object
// and returns the value of its 'name' property

// Sort list of objects by method result (sort list of users by their age)
$sortedByAge = sorted($users, methodCaller('getAge'));
$sortedByAgeDesc = sorted($users, true, methodCaller('getAge'));

// methodCaller('getAge') returns a function which takes an object
// and returns the result of its getAge() method

Sorting with a comparison function

使用比较功能排序

// Sort with a comparison function (order words lexicographically with strcmp)
$sortedLexicographically = sorted(['bc', 'a', 'abc'], false, null, 'strcmp');

// Sort with user-defined comparison function (order words by the 1st character)
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], false, null, function($v1, $v2) {
    return chr($v1[0]) - chr($v2[0]);
});

You can see all these examples here.

您可以在此处查看所有这些示例。

回答by mickmackusa

This page is very comprehensive, but I want to add a bit more about the awesome utility of the spaceship operator (three way comparison operator) -- a beautiful child of PHP7+.

这个页面非常全面,但我想再补充一点关于宇宙飞船运算符(三向比较运算符)——一个 PHP7+ 的漂亮孩子——的很棒的实用程序。

Using the spaceship operator to implement multiple sort conditions

使用飞船算子实现多种排序条件

This makes great strides in reducing code bloat and improving readability.

这在减少代码膨胀和提高可读性方面取得了长足的进步。

When writing your custom sort (usort()/uasort()/uksort()) function to process a multiple conditions, you only need to write balanced arrays on either side of the operator and return the outcome. No more nested condition blocks or multiple returns.

在编写自定义排序(usort()/ uasort()/ uksort())函数来处理多个条件,你只需要编写的运算符两边平衡阵列,并返回结果。不再有嵌套的条件块或多次返回。

The elements from both sides of the operator will be traversed left to right, one at a time, and returning the evaluation as soon as a non-tie is encountered or when the elements have all been compared.

运算符两侧的元素将从左到右遍历,一次一个,并在遇到非平局或元素都已比较时返回评估。

Sample data for my demonstrations:

我的演示的示例数据:

$multidimArray = [
    'a' => [
        'boolean' => true,
        'natString' => 'text10',
        'object' => (object)['prop' => 2],
        'float' => -.5,
        'mixed' => []
    ],
    'b' => [
        'boolean' => true,
        'natString' => 'text12',
        'object' => (object)['prop' => 4],
        'float' => 0,
        'mixed' => null
    ],
    'c' => [
        'boolean' => false,
        'natString' => 'text100',
        'object' => (object)['prop' => 9],
        'float' => -.5,
        'mixed' => false
    ],
    'd' => [
        'boolean' => true,
        'natString' => 'text1',
        'object' => (object)['prop' => 9],
        'float' => -5,
        'mixed' => "
uasort($multidimArray, function($a, $b) {
    return [$b['boolean'], $a['float']] <=> [$a['boolean'], $b['float']];
});
" ], 'e' => [ 'boolean' => false, 'natString' => 'text2', 'object' => (object)['prop' => 2], 'float' => .5, 'mixed' => '' ] ];

Demonstrations (to avoid Stackoverflow page bloat, please see the demo linkfor the outputs):

演示(为避免 Stackoverflow 页面膨胀,请参阅输出的演示链接):

  • Sorting logic:

    1. boolean DESC (false = 0, true = 1, so trues before falses)
    2. float ASC

      uasort($multidimArray, function($a, $b) {
          return [$a['mixed'], $a['object']->prop, $a['boolean']] <=> [$b['mixed'], $b['object']->prop, $b['boolean']];
      });
      
  • Sorting logic:

    1. mixed ASC
    2. object ASC
    3. boolean ASC

      uasort($multidimArray, function($a, $b) {
          return [count(get_object_vars($a['object'])), is_iterable($a['mixed']), strlen($a['natString']), $a['natString']]
                 <=>
                 [count(get_object_vars($b['object'])), is_iterable($b['mixed']), strlen($b['natString']), $b['natString']];
      });
      
  • Sorting logic:

    1. property count of object ASC
    2. iterability of mixed DESC
    3. natString length ASC
    4. natString ASC

      uasort($multidimArray, function($a, $b) {
          return [$b['boolean'], $a['float']] <=> [$a['boolean'], $b['float']];
      });
      
  • 排序逻辑:

    1. boolean DESC (false = 0, true = 1, 所以在 false 之前为真)
    2. 浮动 ASC

      uasort($multidimArray, function($a, $b) {
          return [$a['mixed'], $a['object']->prop, $a['boolean']] <=> [$b['mixed'], $b['object']->prop, $b['boolean']];
      });
      
  • 排序逻辑:

    1. 混合ASC
    2. 对象 ASC
    3. 布尔型 ASC

      uasort($multidimArray, function($a, $b) {
          return [count(get_object_vars($a['object'])), is_iterable($a['mixed']), strlen($a['natString']), $a['natString']]
                 <=>
                 [count(get_object_vars($b['object'])), is_iterable($b['mixed']), strlen($b['natString']), $b['natString']];
      });
      
  • 排序逻辑:

    1. 对象 ASC 的属性计数
    2. 混合 DESC 的可迭代性
    3. natString 长度 ASC
    4. 字符串 ASC

      $collection->sortBy('forename')->sortBy('surname');
      

This syntax allows you to sort values, functional outcomes, deep-nested data, and sorting direction in a elegant fashion. This is definitely worth putting in your php toolbelt ...for cases when you are processing non-database data -- because of course SQL would be a much more sensible technique.

此语法允许您以优雅的方式对值、函数结果、深层嵌套数据和排序方向进行排序。这绝对值得放在您的 php 工具带中……对于处理非数据库数据的情况——当然,SQL 将是一种更明智的技术。

At your own discretion, from PHP7.4 you can use arrow syntax with these anonymous functions. Same script with arrow syntax.

从 PHP7.4 开始,您可以自行决定对这些匿名函数使用箭头语法。 与箭头语法相同的脚本

回答by Rizerzero

If someone wants a simpler solution to manipulate arrays, just use Laravel Collection package which has an implemented sortBy function that lets your sort by keys simply.

如果有人想要一个更简单的解决方案来操作数组,只需使用 Laravel Collection 包,它具有一个实现的 sortBy 函数,可以让您简单地按键排序。

sortBy('c')->sortBy('b')->sortBy('a')

i.e., in order to sort first by a, then b, then c, the correct clause would be

即,为了先按 a、b、c 排序,正确的子句是

##代码##

https://packagist.org/packages/tightenco/collect

https://packagist.org/packages/tightenco/collect