How to Sort a Multi-dimensional Array by Value

1,019,633

Solution 1

Try a usort. If you are still on PHP 5.2 or earlier, you'll have to define a sorting function first:

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

usort($myArray, 'sortByOrder');

Starting in PHP 5.3, you can use an anonymous function:

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

And finally with PHP 7 you can use the spaceship operator:

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

To extend this to multi-dimensional sorting, reference the second/third sorting elements if the first is zero - best explained below. You can also use this for sorting on sub-elements.

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

If you need to retain key associations, use uasort() - see comparison of array sorting functions in the manual.

Solution 2

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

Solution 3

I use this function:

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

Edit This answer is at least ten years old, and there are likely better solutions now, but I am adding some extra info as requested in a couple of comments.

It works because array_multisort() can sort multiple arrays. Example input:

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

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

First $sort_col is made which is an two dimensional array with the values being what we want to sort by and the keys matching the input array. For example for this input, choosing key $sort_col "order" we get:

Array
(
    [0] => 3,
    [1] => 2
)

array_multisort() then sorts that array (resulting in key order 1, 0) but this is only the two dimensional array. So the original input array is also passed as the $rest argument. As the keys match it will be sorted so its keys are also in the same order, giving the desired result.

Note:

  • it is passed by reference so that the supplied array is modified in place.
  • array_multisort() can sort multiple additional array like this, not just one

Solution 4

To achieve this we can use "array_multisort" method which 'Sorts multiple or multi-dimensional arrays'. It's method parameters are

  • $keys - an array being sorted
  • SORT_ASC - sort order (ascending)
  • sort flags (compare items normally(don't change types) or numerically or as strings)
  • $new - then rest of the arrays. Only elements corresponding to equivalent elements in previous
    arrays are compared.

'sort flags' is SORT_REGULAR by default and it is omitted.

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

Result:

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

Solution 5

I usually use usort, and pass my own comparison function. In this case, it is very simple:

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

In PHP 7 using the spaceship operator:

usort($array, function($a, $b) {
    return $a['order'] <=> $b['order'];
});
Share:
1,019,633
stef
Author by

stef

Updated on March 10, 2022

Comments

  • stef
    stef about 2 years

    How can I sort this array by the value of the "order" key?

    Even though the values are currently sequential, they will not always be.

    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
            )
    )
    
  • Sean H
    Sean H over 7 years
    How does this answer the question of sorting by a particular array key?
  • benftwc
    benftwc about 6 years
    "Let's face it: php does NOT have a simple out of the box function to properly handle every array sort scenario." That's exactly what usort/ksort/asort are designed for ^^'
  • axiac
    axiac almost 6 years
    Actually PHP has a lot of sorting functions that can be used to handle every array sort scenario.
  • Will B.
    Will B. about 5 years
    With regard to debugging and maintenance, the use of global is a huge red flag and is generally discouraged. Why is mysql_fetch_array being demonstrated for this question instead of the OP's source array, and that there is no explanation of what your code is doing and what one can expect the outcome to be? Overall this is a very complex approach at achieving the desired end result.
  • Will B.
    Will B. about 5 years
    @tonygil I am not able to determine what your expected results are from your answer and the the OP's dataset. It may be obvious to you, but I do not know how your answer answers the OP's question. However, you can pass by-reference instead of using global see: 3v4l.org/FEeFC This produces an explicitly defined variable, rather than one that can be changed and accessed globally.
  • Kami Yang
    Kami Yang about 4 years
    Note that this approach will emit a notice. array_multisort references it’s first parameter.
  • dWinder
    dWinder over 3 years
  • mickmackusa
    mickmackusa over 3 years
    @Kami there is no evidence of your claim in the ready-made demo link. I wouldn't use this answer because array_column() is more appropriate/concise.
  • mickmackusa
    mickmackusa over 3 years
    This answer is missing its educational explanation.
  • mickmackusa
    mickmackusa over 3 years
    @Nitro This answer is missing its educational explanation. This answer appears to be the correct answer to a different question.
  • mickmackusa
    mickmackusa over 3 years
    This is a less-refined version of ajuchacko91's earlier posted answer.
  • mickmackusa
    mickmackusa over 3 years
    This answer is ignoring the OP's requirements. The question asks how to sort on the order column. Regardless, the spaceship operator (demonstrated in the accepted answer) performs this same comparison without making iterated function calls.
  • mickmackusa
    mickmackusa over 3 years
    A loop, then a native sort, then another loop? Certainly not the most elegant or performant snippet on the page.
  • mickmackusa
    mickmackusa over 3 years
    If you need fallback/tiebreaker sorting without any function calls to prepare values, then declare an array of rules on both sides of a single spaceship operator. 1 2 If subsequent sorting rules incorporate functional overhead, then use the ?: (ternary operator) between subsequent spaceship operator comparisons. 3 so that no extra functions are unnecessarily called.
  • Peter Mortensen
    Peter Mortensen almost 3 years
    An explanation would be in order.
  • Peter Mortensen
    Peter Mortensen almost 3 years
    An explanation would be in order. E.g., what is the idea/gist? What are the tradeoffs compared to other solutions? What are the performance characteristics, both theoretical and actual examples performance measurements? For instance, is this solution dog slow or not?
  • Peter Mortensen
    Peter Mortensen almost 3 years
    Do all these options result in a stable sort?
  • mickmackusa
    mickmackusa over 2 years
    This question is only sorting on one column. Your answer caters more to this page: stackoverflow.com/q/3232965/2943403 and stackoverflow.com/q/7127764/2943403
  • Meas
    Meas over 2 years
    It works thank how about DESC ?
  • mickmackusa
    mickmackusa over 2 years
    This answer is too much of a departure from the original question. How can researchers compare this solution against the other answers and arrive at a favorite if this snippet doesn't resemble the question's sample data?
  • mickmackusa
    mickmackusa over 2 years
    @Meas for DESC sorting, you reverse the position of the a and the b relative to the <=>. See this answer.
  • Shivanand Sharma
    Shivanand Sharma over 2 years
    How difficult would it be to reverse the order? Can the fn be changed or does it call for an array_reverse?
  • theking2
    theking2 almost 2 years
    Excellent and modern answer. this needs upvotes.
  • theking2
    theking2 almost 2 years
    Tiny detail it is called the spaceship operator.
  • dılo sürücü
    dılo sürücü almost 2 years
    uasort($yourArray, fn($a, $b) => -1*($a['order'] <=> $b['order'])); reverse...
  • Eric P
    Eric P almost 2 years
    While I liked learning about the spaceship operator, this seems the most understandable and straightforward answer with useful options like SORT_DESC and multiple options for sort_flags (php.net/manual/en/function.array-multisort.php).
  • mickmackusa
    mickmackusa almost 2 years
    An earlier demonstration of multi-column sorting of which there will be many on Stack Overflow in the last 14 years of content generation. And another
  • mickmackusa
    mickmackusa almost 2 years
    And this one. Hmm the more I re-read the question and this answer, it seems that this answer should have been posted on a different page because it is duplicating the advice in the accepted answer and then extends the question scope. It would have been better to find a page that doesn't yet demonstrate how to sort on multiple columns.
  • Guillermo Phillips
    Guillermo Phillips almost 2 years
    I guess I would be agnostic about where my answer belongs. You're right that I answered more than the question asked. People will find either this question or the other ones, so there is more likelihood that they will come across our answers and this (easy) way of sorting. We just need upvotes!