如何按值对多维数组进行排序?


1128

如何按“订单”键的值对该数组排序?即使这些值当前是连续的,也不会总是如此。

Array
(
    [0] => Array
        (
            [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
            [title] => Flower
            [order] => 3
        )

    [1] => Array
        (
            [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
            [title] => Free
            [order] => 2
        )

    [2] => Array
        (
            [hashtag] => e7d31fc0602fb2ede144d18cdffd816b
            [title] => Ready
            [order] => 1
        )
)


最快的方法是使用同构排序数组模块,该模块可在浏览器和节点中本机运行,支持任何类型的输入,计算字段和自定义排序顺序。
劳埃德

Answers:


1730

尝试使用usort,如果您仍然使用PHP 5.2或更早版本,则必须首先定义一个排序函数:

function sortByOrder($a, $b) {
    return $a['order'] - $b['order'];
}

usort($myArray, 'sortByOrder');

从PHP 5.3开始,您可以使用匿名函数:

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

最后,在PHP 7中,您可以使用spaceship运算符

usort($myArray, function($a, $b) {
    return $a['order'] <=> $b['order'];
});

要将其扩展到多维排序,如果第二个/第三个排序元素为零,请参考第二个/第三个排序元素-下文将详细说明。您也可以使用它对子元素进行排序。

usort($myArray, function($a, $b) {
    $retval = $a['order'] <=> $b['order'];
    if ($retval == 0) {
        $retval = $a['suborder'] <=> $b['suborder'];
        if ($retval == 0) {
            $retval = $a['details']['subsuborder'] <=> $b['details']['subsuborder'];
        }
    }
    return $retval;
});

如果需要保留键关联,请使用uasort()-请参见手册中数组排序功能的比较


2
我的措词有点偏离,我将对其进行编辑。我的意思是,如果您使用的不是PHP 5.3,则需要为该特定排序创建一个特殊的函数(这在某种程度上不是很优雅)。否则,您可以在那里使用匿名函数。
Christian Studer 2010年

23
@Jonathan:您真的看不到PHP可以完成的大部分工作。它接受数组,并以两个元素开头,并将其传递给此用户定义的函数。然后,您的函数负责对其进行比较:如果第一个元素大于第二个元素,则返回一个正整数,如果较小,则返回一个负整数。如果它们相等,则返回0。然后,PHP将另外两个元素发送到您的函数,并继续这样做,直到对数组进行排序为止。这里的函数很短,如果您不比较整数,它可能会复杂得多。
Christian Studer

61
提示:uasort()如果要保留阵列键,请使用。
thaddeusmt

15
如果可排序的值是十进制数字,请小心。如果排序函数get的$ a = 1和$ b = 0.1,则差为0.9,但该函数返回一个int,在这种情况下为0,因此将$ a和$ b视为相等,并且排序不正确。比较$ a是否大于或等于$ b并返回-1、1或0更为可靠。
格陵兰

37
我花了一段时间才找到答案。要对反向顺序(DESC)进行排序,可以切换$ a和$ b。因此$ b ['order']-$ a ['order']
JanWillem 2014年

285
function aasort (&$array, $key) {
    $sorter=array();
    $ret=array();
    reset($array);
    foreach ($array as $ii => $va) {
        $sorter[$ii]=$va[$key];
    }
    asort($sorter);
    foreach ($sorter as $ii => $va) {
        $ret[$ii]=$array[$ii];
    }
    $array=$ret;
}

aasort($your_array,"order");

7
@ noc2spam我很高兴能为您提供帮助,但是请考虑遵循studer的建议,该建议可能更有效,而且肯定会更整洁!
o0'。

1
@Lohoris肯定,伙计,我也在检查。如果我没发现这个问题,昨天在办公室里将会是艰难的一天:-)
Gogol 2013年

嗯不能添加答案..好吧,我把它放在这里,因为我不需要那些愚蠢的观点:所以对于多维排序,它(几乎)是同一件事(很抱歉,您必须复制粘贴并重新格式化):function aasort(&$ array ,$ key1,$ key2,$ key3){$ sorter = array(); $ ret = array(); reset($ array); foreach($ array as $ ii => $ va){$ sorter [$ ii] = getPrice($ va [$ key1] [$ key2] [$ key3]); } arsort($ sorter); foreach($ sorter as $ ii => $ va){$ ret [$ ii] = $ array [$ ii]; } $ array = $ ret; }
Jaxx0rr

3
比上述答案更容易应用
Marcel

1
你真棒!!像PHP 7.2一样吸引人的工作,谢谢:)
Kamlesh

270

我使用这个功能:

function array_sort_by_column(&$arr, $col, $dir = SORT_ASC) {
    $sort_col = array();
    foreach ($arr as $key=> $row) {
        $sort_col[$key] = $row[$col];
    }

    array_multisort($sort_col, $dir, $arr);
}


array_sort_by_column($array, 'order');

3
效果很好。能够添加排序方向的独特解决方案。谢谢!
伊沃·佩雷拉

2
对于支持排序方向和许多其他功能的替代方案,您可能想在这里看看我的答案 -它还具有不使用array_multisort且因此不需要预先分配的优点,从而$sort_col节省了时间和内存。
乔恩

对我来说效果很好,但是...为什么需要指定&$arr而不是$arr
Radu Murzea 2013年

2
@RaduMurzea,因此该数组通过引用传递,并且可以通过函数进行修改,而不是通过函数接收副本进行修改
Tom Haigh 2013年

1
@AdrianP。:该数组是通过引用传递的,因此它将修改传递的数组,而不是返回已排序的副本
Tom Haigh,2016年

72

我通常使用usort,并传递自己的比较函数。在这种情况下,这非常简单:

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

在PHP 7中使用飞船运算符:

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

4
该死,我慢了30秒。不是$ a-$ b吗?
Christian Studer 2010年

3
我总是会错。让我从手册中考虑:如果第一个参数小于第二个参数,则返回值必须小于零。因此,如果$a['order']为3,$b['order']为6,我将返回-3。正确?
Jan Fabry'4

3
好吧,您返回b-a,因此它将是3。因此排序不正确。
Christian Studer 2010年

26
啊。好。我使用的是非逻辑算术,您脑海中的想法与您产生的单词不符。星期五下午最常对此进行研究。
Jan Fabry

在上面的回答有些情况下是返回错误的结果..参考stackoverflow.com/questions/50636981/...
比拉尔·艾哈迈德

45

实现这一目标的一种方法是这样的

    $new = [
              [
                'hashtag' => 'a7e87329b5eab8578f4f1098a152d6f4',
                'title' => 'Flower',
                'order' => 3,
              ],

              [
                'hashtag' => 'b24ce0cd392a5b0b8dedc66c25213594',
                'title' => 'Free',
                'order' => 2,
              ],

              [
                'hashtag' => 'e7d31fc0602fb2ede144d18cdffd816b',
                'title' => 'Ready',
                'order' => 1,
              ],
    ];

    $keys = array_column($new, 'order');

    array_multisort($keys, SORT_ASC, $new);

    var_dump($new);

结果:

    Array
    (
        [0] => Array
            (
                [hashtag] => e7d31fc0602fb2ede144d18cdffd816b
                [title] => Ready
                [order] => 1
            )

        [1] => Array
            (
                [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
                [title] => Free
                [order] => 2
            )

        [2] => Array
            (
                [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
                [title] => Flower
                [order] => 3
            )

    )

18

要使用“ title”键的值对数组进行排序,请使用:

uasort($myArray, function($a, $b) {
    return strcmp($a['title'], $b['title']);
});

strcmp比较字符串。

uasort()维护定义的数组键。


strcmp是varchar类型的显着帮助,我很快又喜欢此答案
StudioX

17
$sort = array();
$array_lowercase = array_map('strtolower', $array_to_be_sorted);
array_multisort($array_lowercase, SORT_ASC, SORT_STRING, $alphabetically_ordered_array);

这会照顾到大小写字母。


4
这如何回答按特定数组键排序的问题?
锡诺

12

使用array_multisort()array_map()

array_multisort(array_map(function($element) {
      return $element['order'];
  }, $array), SORT_ASC, $array);

print_r($array);

演示


请注意,此方法将发出通知。array_multisort引用它的第一个参数。
Kami Yang

5

最灵活的方法是使用此方法

Arr::sortByKeys(array $array, $keys, bool $assoc = true): array

原因如下:

  • 您可以按任意键进行排序(也嵌套为'key1.key2.key3'['k1', 'k2', 'k3']

  • 对关联数组和非关联数组均起作用($assoc标志)

  • 它不使用引用-返回新的排序数组

在您的情况下,它很简单:

$sortedArray = Arr::sortByKeys($array, 'order');

此方法是该库的一部分。


1

让我们面对现实:php没有简单的开箱即用功能来正确处理每个数组排序方案。

此例程非常直观,这意味着可以更快地进行调试和维护:

// automatic population of array
$tempArray = array();
$annotations = array();
// ... some code
// SQL $sql retrieves result array $result 
// $row[0] is the ID, but is populated out of order (comes from 
// multiple selects populating various dimensions for the same DATE 
// for example
while($row = mysql_fetch_array($result)) {
    $needle = $row[0];
    arrayIndexes($needle);  // create a parallel array with IDs only
    $annotations[$needle]['someDimension'] = $row[1]; // whatever
}
asort($tempArray);
foreach ($tempArray as $arrayKey) {
    $dataInOrder = $annotations[$arrayKey]['someDimension']; 
    // .... more code
}

function arrayIndexes ($needle) {
    global $tempArray;
    if (!in_array($needle,$tempArray)) {
        array_push($tempArray,$needle);
    }
}

4
“面对现实:php没有简单的即用即用功能来正确处理每个数组排序方案。” 这正是usort / ksort / ASORT是专为^^”
奔Cassinat

3
实际上,PHP 具有 许多可用于处理每个数组排序方案的排序功能
axiac

对于调试和维护,使用的global是一个巨大的红旗,并且一般不提倡。为什么mysql_fetch_array要为这个问题而不是OP的源数组进行演示,并且没有解释您的代码在做什么以及可以预期结果是什么?总体而言,这是实现所需最终结果的非常复杂的方法。
菲尔耶(Fyrye)

@tonygil我无法根据您的答案和OP的数据集确定您的预期结果。对于您来说,这可能很明显,但是我不知道您的回答如何回答了OP的问题。但是,您可以传递引用而不是使用global3v4l.org/FEeFC这将产生一个显式定义的变量,而不是可以全局更改和访问的变量。
fyrye

0

您还可以将多维数组排序为多个值,例如

$arr = [
    [
        "name"=> "Sally",
        "nick_name"=> "sal",
        "availability"=> "0",
        "is_fav"=> "0"
    ],
    [
        "name"=> "David",
        "nick_name"=> "dav07",
        "availability"=> "0",
        "is_fav"=> "1"
    ],
    [
        "name"=> "Zen",
        "nick_name"=> "zen",
        "availability"=> "1",
        "is_fav"=> "0"
    ],
    [
        "name"=> "Jackson",
        "nick_name"=> "jack",
        "availability"=> "1",
        "is_fav"=> "1"
    ],
    [
        "name"=> "Rohit",
        "nick_name"=> "rod",
        "availability"=> "0",
        "is_fav"=> "0"
    ],

];

usort($arr,function($a,$b){
    $c = $b['is_fav'] - $a['is_fav'];
    $c .= $b['availability'] - $a['availability'];
    $c .= strcmp($a['nick_name'],$b['nick_name']);
    return $c;
});

使用输出print_r($arr)

Array
(
    [0] => Array
        (
            [name] => Jackson
            [nick_name] => jack
            [availability] => 1
            [is_fav] => 1
        )

    [1] => Array
        (
            [name] => David
            [nick_name] => dav07
            [availability] => 0
            [is_fav] => 1
        )

    [2] => Array
        (
            [name] => Zen
            [nick_name] => zen
            [availability] => 1
            [is_fav] => 0
        )

    [3] => Array
        (
            [name] => Rohit
            [nick_name] => rod
            [availability] => 0
            [is_fav] => 0
        )

    [4] => Array
        (
            [name] => Sally
            [nick_name] => sal
            [availability] => 0
            [is_fav] => 0
        )

)

PS)使用strcmp是比较字符串的一个不错的选择。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.