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

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


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

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


当前回答

最简单的方法是使用usort函数对数组进行排序,而不需要任何循环: 下面是一个例子:

   $array_compare= array("0" =>4,"1"=>2,"2"=>500,"3"=>100);

这将按降序排序:

usort($array_compare, function($a, $b) {
        return ($b['x1'] - $a['x1']) > 0 ? 1 :-1;
    });

这将按发送顺序排序:

usort($array_compare, function($a, $b) {
        return ($b['x1'] - $a['x1']) < 0 ? 1 :-1;
    });

其他回答

基本一维数组

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

适用的排序函数:

排序 函数 带点 arsort 的作用 natcasesort ksort 作用

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

多维数组,包括对象数组

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

如果你想根据每个条目的'foo'键对$array排序,你需要一个自定义比较函数。上面的排序和相关函数工作在简单的值上,它们知道如何比较和排序。PHP并不简单地“知道”如何处理复杂的值,例如数组('foo' => 'bar', 'baz' => 42);所以你需要讲出来。

为此,需要创建一个比较函数。该函数接受两个元素,如果认为这两个元素相等,则必须返回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;
    }
}

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

然后使用下列函数之一:

usort uasort uksort

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

使用示例:

usort($array, 'cmp');

usort will take two items from the array and call your cmp function with them. So cmp() will be called with $a as array('foo' => 'bar', 'baz' => 42) and $b as another array('foo' => ..., 'baz' => ...). The function then returns to usort which of the values was larger or whether they were equal. usort repeats this process passing different values for $a and $b until the array is sorted. The cmp function will be called many times, at least as many times as there are values in $array, with different combinations of values for $a and $b every time.

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

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

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

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

Sort通过引用进行排序,不返回任何有用的东西!

请注意,数组排序到位,您不需要将返回值分配给任何东西。$array = sort($array)将数组替换为true,而不是一个排序的数组。只是数组($);的工作原理。

自定义数值比较

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

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

感谢MATH的力量,这将返回一个< 0,0或> 0的值,取决于$a是否小于、等于或大于$b。

注意,这对于浮点值并不适用,因为它们将被简化为int并失去精度。使用显式的-1、0和1返回值代替。

对象

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

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

功能

你可以在比较函数中做任何你需要做的事情,包括调用函数:

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

字符串

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

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

STRCMP和CMP完全一样,它返回-1 0或1。

宇宙飞船操作符

PHP 7引入了宇宙飞船操作符,它统一并简化了不同类型之间的相等/较小/较大比较:

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

按多个字段排序

如果你想主要根据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'];
    }
}

对于那些熟悉的人来说,这相当于一个带有ORDER BY foo, baz的SQL查询。 还可以查看这个非常简洁的简写版本,以及如何为任意数量的键动态创建这样的比较函数。

按手动、静态顺序排序

如果你想将元素按“手动顺序”排序,比如“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);
}

对于上述所有问题,如果你使用的是PHP 5.3或更高版本(你真的应该这样做),请使用匿名函数来缩短代码,并避免出现另一个全局函数:

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

这就是对一个复杂的多维数组进行排序的简单程度。同样,就像教PHP如何分辨两个项中哪一个“更大”一样;让PHP来做实际的排序。

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

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

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

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

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

这里的预期结果是:

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

使用array_multisort来实现:

array_multisort($array1, $array2);

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

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

你也可以对多个列进行排序:

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

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


如果你有更多的常见情况,请随意编辑这个答案。

如果你想根据多个标准的绝对最大值对数组进行排序,这里有一个简单的方法:

usort($arr, function($item, $nextItem) {
    return (max($nextItem->firstNumber, $nextItem->secondNumber)) - (max($item->firstNumber, $item->secondNumber));
});

例子:

$foo = new stdClass;
$foo->createdDate = '10';
$foo->uploadedDate = '5';

$bar = new stdClass;
$bar->createdDate = '1';
$bar->uploadedDate = '12';

$baz = new stdClass;
$baz->createdDate = '25';
$baz->uploadedDate = '0';


$arr = [$foo, $bar, $baz];

// Order array by the highest number between "createdDate" and "uploadedDate".
usort($arr, function($item, $nextItem) {
    return (max($nextItem->createdDate, $nextItem->uploadedDate)) - (max($item->createdDate, $item->uploadedDate));
});

结果:

array (
  0 => 
  (object) array(
     'createdDate' => '25',
     'uploadedDate' => '0',
  ),
  1 => 
  (object) array(
     'createdDate' => '1',
     'uploadedDate' => '12',
  ),
  2 => 
  (object) array(
     'createdDate' => '10',
     'uploadedDate' => '5',
  ),
)

LINQ

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

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

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

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

这里,'$v->count'是函数($v) {return $v->count;}(任何一个都可以使用)。这些方法链返回迭代器,迭代器可以通过在最后添加->toArray()转换为数组。

在内部,orderBy和相关方法调用适当的数组排序函数(uasort、krsort、multisort、usort等)。

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

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

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

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

这个答案是关于多列排序的,其中数组应该在每个一维元素中根据非连续索引的值进行排序。 这与多维排序不同,因为每个元素只由不同的Key=>Value对组成。

function fncCmp( array $ItmOne, array $ItmTwo ) {       ; # callback for sorting items (which are arrays) by values at specific indexes
  $strCmpOne = $ItmOne[ 'ColOne' ] . $ItmOne[ 'ColThr' ]; # build compound values
  $strCmpTwo = $ItmTwo[ 'ColOne' ] . $ItmTwo[ 'ColThr' ]; #   to compare
  return $strCmpOne <=> $strCmpTwo                      ; # pass back comparison-result
} # fncCmp

$arrDat = array(                                                       # define an array of items
  array( 'ColOne' => 'Val2', 'ColTwo' => 'Val8', 'ColThr' => 'Val6' )  #   each of which
 ,array( 'ColOne' => 'Val2', 'ColTwo' => 'Val9', 'ColThr' => 'Val4' )  #   is an
 ,array( 'ColOne' => 'Val1', 'ColTwo' => 'Val7', 'ColThr' => 'Val5' )  #   array of
)                                                                    ; #   fields
var_dump       ( $arrDat           )                                 ; # emit items before sort
$bolSrt = usort( $arrDat, 'fncCmp' )                                 ; # sort the array by comparing elements
var_dump       ( $arrDat           )                                 ; # emit items after  sort