这个问题旨在作为PHP中关于数组排序的问题的参考。很容易认为您的特定情况是独特的,值得提出一个新问题,但大多数情况实际上是本页上某个解决方案的微小变化。 如果你的问题是这个问题的副本,请要求重新打开你的问题,只有当你能解释为什么它与下面所有的问题都有显著不同时。

我如何排序一个数组在PHP? 我如何排序一个复杂的数组在PHP? 如何在PHP中排序对象数组?


基本一维数组;包括多维数组,包括对象数组;包括根据一个数组对另一个数组排序 用SPL排序 稳定的排序

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


当前回答

有几种方法可以对数组进行排序。我将提到一些完成这项任务的方法。首先,我将给出一个整数数组,称为'$numbers'。

$number = array(8,9,3,4,0,1,2);

这是创建数组的正常方式。假设我想要对这个数组进行升序排序。为此,可以使用'sort()'方法。

<?php

    $number = array(8,9,3,4,0,1,2);
    sort($number);

   foreach ($number as $value) {
       echo $value."  ";
   }
?>

现在考虑它的输出,

你可以看到打印的数字数组是排序的。如果你想要该数字数组排序是降序的,'rsort()'方法可以用于该任务。

<?php

     $number = array(8,9,3,4,0,1,2);
     rsort($number);

     foreach ($number as $value) {
        echo $value."  ";
     }
?>

考虑输出..

现在数组按降序排序。让我们考虑一个关联数组。我将给出一个关联数组(关联数组的意思是,每个索引都有唯一键值的数组),就像这样,

$number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);

那么,现在我想根据它们的值对这个数组进行升序排序。' sort()'方法可以用于此。

<?php

   $number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);
   asort($number);

   foreach ($number as $value) {
      echo $value."  ";
    }
?>

如果根据它们的值降序排序,则可以使用'arsort()'方法。 假设您想要根据键值对数组进行排序。在这种情况下,可以使用'ksort()'方法。

<?php

     $number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);
     ksort($number);

     foreach ($number as $value) {
         echo $value."  ";
     }
?>

现在考虑输出。

现在数组根据它们的键值排序。如果您想根据键值降序排序数组,可以使用'krsort()'方法。

<?php

    $number = array('eight'=>8,'nine'=>9,'three'=>3,'fore'=>4,'zero'=>0,'one'=>1,'two'=>2);
    krsort($number);

    foreach ($number as $value) {
       echo $value."  ";
    }
?>

现在,关联数组按照键值降序排序。看看输出。

这些是php中按升序或降序排序数组的一些方法。我希望你能有所了解。谢谢你!

其他回答

大多数基本的方法都已经讲过了,我会试着看看其他类型的排序

用SPL排序

碎片堆

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));

输出

c
b
a

SplMaxHeap

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

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

SplMinHeap

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

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

其他类型的排序

冒泡排序

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

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;
}

选择排序

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

在计算机科学中,选择排序是一种排序算法,特别是就地比较排序。它有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;
}

插入排序

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

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

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

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

Shellsort,也称为Shell排序或Shell的方法,是一种就地比较排序。它泛化了交换排序,例如插入排序或冒泡排序,方法是先与相距很远的元素比较和交换元素,然后再与相邻的元素完成比较和交换。

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;
}

梳子排序

摘自维基百科关于梳状排序的文章:

梳状排序是由Wlodzimierz Dobosiewicz在1980年设计的一种相对简单的排序算法。后来,它在1991年被斯蒂芬·莱西和理查德·博克斯重新发现。梳状排序改进了冒泡排序。

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;
}

去排序

摘自维基百科关于归并排序的文章:

在计算机科学中,归并排序(也通常拼写为mergesort)是一种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;
}

快速排序

维基百科上关于快速排序的文章:

快速排序,或分区交换排序,是由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));
}

排列排序

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

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

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排序的文章:

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

// 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;
}

按键值进行多维排序

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

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;
}

测试用例:

$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,
  ),
)
*/

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

使用太空船操作符实现多个排序条件

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

当编写自定义sort(usort()/uasort()/uksort())函数来处理多个条件时,只需要在运算符的两侧编写平衡数组并返回结果。没有更多嵌套的条件块或多个返回。

操作符两边的元素将从左到右遍历,一次一个,一旦遇到不连接的元素或元素都进行了比较,就返回求值。

用于演示的示例数据:

$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' => "\0"
    ],
    'e' => [
        'boolean' => false,
        'natString' => 'text2',
        'object' => (object)['prop' => 2],
        'float' => .5,
        'mixed' => ''
    ]
];

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

Sorting logic: boolean DESC (false = 0, true = 1, so trues before falses) float ASC uasort($multidimArray, function($a, $b) { return [$b['boolean'], $a['float']] <=> [$a['boolean'], $b['float']]; }); Sorting logic: mixed ASC object ASC boolean ASC uasort($multidimArray, function($a, $b) { return [$a['mixed'], $a['object']->prop, $a['boolean']] <=> [$b['mixed'], $b['object']->prop, $b['boolean']]; }); Sorting logic: property count of object ASC iterability of mixed DESC natString length ASC natString 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']]; });

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

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

稳定的排序

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

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

现在你只想对第一个字母排序:

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

结果是:

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

那种东西不稳定!

敏锐的观察者可能已经注意到,数组排序算法(快速排序)并没有产生稳定的结果,并且相同首字母的单词之间的原始顺序没有被保留。这种情况很简单,我们应该比较整个字符串,但是让我们假设您的用例更复杂,比如在不同的字段上连续进行两次排序,它们不应该相互抵消。

施瓦兹变换

Schwartzian变换,也称为装饰-排序-不装饰习语,它使用固有的不稳定排序算法来实现稳定排序。

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

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

这将数组转换为:

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

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

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
});

之后,我们进行装饰:

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

最终结果:

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

重用呢?

你必须重写比较函数来处理转换后的数组元素;你可能不想编辑你精致的比较函数,所以这里有一个比较函数的包装器:

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];
        }
    };
}

让我们使用这个函数来编写排序步骤:

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

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

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

基本分类

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

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

按函数结果排序

// 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

多维数组排序

// Sort multidimensional array (sort list of users by their names)
$users = [
    array('name' => 'Robert', 'age' => 20),
    array('name' => 'Alex', 'age' => 30),
    array('name' => 'Jack', '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

对象排序数组

// 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('Jack', 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

用比较函数排序

// 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]);
});

你可以在这里看到所有这些例子。