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

新手上路,请多包涵

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

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

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

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

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


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

  2. 使用 SPL 排序

  3. 稳定排序

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

原文由 deceze 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 847
2 个回答

基本一维数组

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

适用的排序功能:

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

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

多维数组,包括对象数组

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

如果要按每个条目的键 ‘foo’ 对 $array 进行排序,则需要 _自定义比较函数_。上述 sort 和相关函数对他们知道如何比较和排序的简单值起作用。 PHP 并不简单地“知道”如何处理像 array('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($array, 'cmp');

usort 将从数组中取出两个项目并调用您的 cmp 函数。 So cmp() will be called with $a as array('foo' => 'bar', 'baz' => 42) and $b as another array('foo' => ..., 'baz' => ...) .然后该函数返回到 usort 哪个值更大或它们是否相等。 usort 重复这个过程,为 $a$b 传递不同的值,直到数组被排序。 cmp 函数将被调用多次, 至少$array 中的值一样多,并且 $b $a 的值组合不同 --- 每次。

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

 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 替换数组,而不是排序数组。只是 sort($array); 有效。

自定义数值比较

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

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

多亏了 The Power oF MATH ,这取决于 $a 是否低于、等于或大于 $b 返回值 < 0、0 或 > 0。

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

对象

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

 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 does exactly what’s expected of cmp here, it returns -1 , 0 or 1 .

宇宙飞船操作员

PHP 7 引入了 spaceship 运算符,它统一并简化了等于/小于/大于跨类型的比较:

 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 开始,您还可以从对象数组中提取属性。


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

原文由 deceze 发布,翻译遵循 CC BY-SA 4.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

原文由 Bilbo 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题