1245

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
        )
)
stef
  • 23,866
  • 28
  • 96
  • 140
  • 1
    Cross-Linked: [Reference: all basic ways to sort arrays and data in PHP](http://stackoverflow.com/q/17364127/367456) – hakre Oct 30 '13 at 09:48
  • the quickest way is to use the isomorphic [sort-array](https://github.com/75lb/sort-array) module which works natively in both browser and node, supporting any type of input, computed fields and custom sort orders. – Lloyd Oct 21 '19 at 20:26

13 Answers13

1909

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

Talk Nerdy To Me
  • 429
  • 2
  • 14
Christian Studer
  • 22,792
  • 6
  • 39
  • 70
  • 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](https://stackoverflow.com/a/61119066/2943403) [2](https://stackoverflow.com/a/44309755/2943403) If subsequent sorting rules incorporate functional overhead, then use the `?:` (ternary operator) between subsequent spaceship operator comparisons. [3](https://stackoverflow.com/a/62276444/2943403) so that no extra functions are unnecessarily called. – mickmackusa Dec 07 '20 at 22:17
291
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");
o0'.
  • 11,246
  • 15
  • 57
  • 84
282

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');
Tom Haigh
  • 54,886
  • 20
  • 107
  • 138
80

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 spaceship operator:

usort($array, function($a, $b) {
    return $a['order'] <=> $b['order'];
});
Jsowa
  • 4,188
  • 4
  • 23
  • 35
Jan Fabry
  • 6,499
  • 1
  • 32
  • 39
74

One approach to achieve this would be like this

$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
        )
)
Roman
  • 2,061
  • 2
  • 22
  • 43
ajuchacko91
  • 879
  • 6
  • 3
21

To sort the array by the value of the "title" key use:

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

strcmp compare the strings.

uasort() maintains the array keys as they were defined.

B.K
  • 681
  • 7
  • 5
  • 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 Dec 07 '20 at 22:01
18

Use array_multisort(), array_map()

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

print_r($array);

DEMO

shazyriver
  • 3,103
  • 4
  • 27
  • 50
Ghanshyam Nakiya
  • 1,077
  • 11
  • 18
17
$sort = array();
$array_lowercase = array_map('strtolower', $array_to_be_sorted);
array_multisort($array_lowercase, SORT_ASC, SORT_STRING, $alphabetically_ordered_array);

This takes care of both upper and lower case alphabets.

Udo Held
  • 11,486
  • 11
  • 63
  • 86
Nitrodbz
  • 1,246
  • 1
  • 15
  • 24
6

The most flexible approach would be using this method

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

here's why:

  • You can sort by any key (also nested like 'key1.key2.key3' or ['k1', 'k2', 'k3'])

  • Works both on associative and not associative arrays ($assoc flag)

  • It doesn't use reference - return new sorted array

In your case it would be as simple as:

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

This method is a part of this library.

Minwork
  • 488
  • 5
  • 6
2

If anyone need sort according to key best is to use below

usort($array, build_sorter('order'));

function build_sorter($key) {
   return function ($a, $b) use ($key) {
      return strnatcmp($a[$key], $b[$key]);
   };
}
Zahid
  • 29
  • 3
1

This solution is for usort() with an easy-to-remember notation for multidimensional sorting. The spaceship operator <=> is used, which is available from PHP 7.

usort($in,function($a,$b){
  return $a['first']   <=> $b['first']  //first asc
      ?: $a['second']  <=> $b['second'] //second asc
      ?: $b['third']   <=> $a['third']  //third desc (a b swapped!)
      //etc
  ;
});

Examples:

$in = [
  ['firstname' => 'Anton', 'surname' => 'Gruber', 'birthdate' => '03.08.1967', 'rank' => 3],
  ['firstname' => 'Anna', 'surname' => 'Egger', 'birthdate' => '04.01.1960', 'rank' => 1],
  ['firstname' => 'Paul', 'surname' => 'Mueller', 'birthdate' => '15.10.1971', 'rank' => 2],
  ['firstname' => 'Marie', 'surname' => 'Schmidt ', 'birthdate' => '24.12.1963', 'rank' => 2],
  ['firstname' => 'Emma', 'surname' => 'Mueller', 'birthdate' => '23.11.1969', 'rank' => 2],
];

first task: Order By rank asc, surname asc

usort($in,function($a,$b){
  return $a['rank']      <=> $b['rank']     //first asc
      ?: $a['surname']   <=> $b['surname']  //second asc
  ;
});

second task: Order By rank desc, surname asc, firstmame asc

usort($in,function($a,$b){
  return $b['rank']      <=> $a['rank']       //first desc
      ?: $a['surname']   <=> $b['surname']    //second asc
      ?: $a['firstname'] <=> $b['firstname']  //third asc
  ;
});

third task: Order By rank desc, birthdate asc

The date cannot be sorted in this notation. It is converted with strtotime.

usort($in,function($a,$b){
  return $b['rank']      <=> $a['rank']       //first desc
      ?: strtotime($a['birthdate']) <=> strtotime($b['birthdate'])    //second asc
  ;
});
jspit
  • 3,933
  • 1
  • 6
  • 13
0

Let's face it: php does NOT have a simple out of the box function to properly handle every array sort scenario.

This routine is intuitive, which means faster debugging and maintenance:

// 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);
    }
}
tony gil
  • 9,063
  • 6
  • 72
  • 89
  • 6
    "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 ^^' – benftwc Apr 23 '18 at 13:19
  • 5
    Actually PHP **has** [a lot of sorting functions](http://php.net/manual/en/array.sorting.php) that can be used to handle every array sort scenario. – axiac May 29 '18 at 16:31
  • 1
    With regard to debugging and maintenance, the use of `global` is a huge red flag and is [generally discouraged](https://stackoverflow.com/a/1558073/1144627). 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. May 01 '19 at 15:50
  • 1
    @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](https://www.php.net/manual/en/language.references.pass.php) instead of using `global` see: https://3v4l.org/FEeFC This produces an explicitly defined variable, rather than one that can be changed and accessed globally. – Will B. May 02 '19 at 21:07
0

You could use usort user-defined sort function with a callback function:

usort($new, fn($a, $b) => $a['order'] - $b['order']);

TRICK: you could use a > b or a - b or a <=> b for sorting in an Ascending order. For a Descending order just swap position of a and b

Steverst1
  • 1,243
  • 1
  • 2
  • 13