1

I have this array :

$order_list = array ( array ("081", "01203", "2", "12000"),
                      array ("002", "01204", "8", NULL),
                      array ("021", "01207", "8", NULL),
                      array ("081", "01206", "8", NULL),
                      array ("043", "01205", "10", "14000"));         

and I want to sort (ascending) that array based on the first value (081, 002, 021, 081 and 043). so it will look like this :

array ( array ("002", "01204", "8", NULL),
        array ("021", "01207", "8", NULL),
        array ("043", "01205", "10", "14000"),
        array ("081", "01203", "2", "12000"),
        array ("081", "01206", "8", NULL));

how to do that? I learned about asort() and ksort(), but it seems that only works for associative array, not multidimensional array.

Saint Robson
  • 5,475
  • 18
  • 71
  • 118

2 Answers2

3

You can use usort()

usort($yourArray, function ($a, $b) {
    if ($a[0] == $b[0]) return 0;
    return (int) $a[0] < (int) $b[0] ? -1 : 1;
});

The parameters $a and $b are your (sub)arrays. This simple function compares the first value in each of those.

If you had other than numbers in your array you could have used strcmp():

usort($yourArray, function ($a, $b) {
    return strcmp($a[0], $b[0]);
});
Michael
  • 2,631
  • 2
  • 24
  • 40
  • Be aware that `usort` exhibits [undefined behavior](http://php.net/manual/en/function.usort.php) (first *Note* in that link) if your sorting function returns `0`. – morido Jan 22 '16 at 11:06
  • @morido, you make it seem worse than it is. It simply states that there is no way of telling if there value 0 is returned then usort cannot tell which of the two (arrays in this case) comes first, which is perfectly fine, since there are deemed to be equal. – Michael Jan 22 '16 at 11:10
  • I am just saying how it is. After all, it's a beautiful source of (hard to find) bugs. So I prefer to *always* make the behavior deterministic and either force `$a` or `$b` to be sorted in first, rather than to leave this to the implementation. – morido Jan 22 '16 at 11:18
  • @morido so what would be the "correct" way to determine -1 or 1 for two arrays that are identical? – Michael Jan 24 '16 at 08:27
  • There is no "correct" way. It's up to you(r personal convention) and/or the requirements of the surrounding logic. But remember: We are not comparing arrays here, we are just comparing two elements of a single array. And *comparison* is not necessarily related to *equality*, either. – morido Jan 24 '16 at 09:18
  • @morido I just wanted to hear your opinion. – Michael Jan 24 '16 at 09:26
  • 1
    Well the point is, that PHP does not make any statements about the order of equal elements. This is different to other languages, where such operations often guarantee *stability* (i.e. predictable behavior) in such situations. See for instance [`Arrays.sort`](https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#sort%28T[],%20java.util.Comparator%29) in Java. – morido Jan 24 '16 at 09:40
  • BTW: If you really need a sort that's *guaranteed* to be stable under all circumstances, you are actually be better off rolling out your own sorting function since PHP does promise anything about the heritage of `$a` and `$b` in the comparator, either. See [here](http://stackoverflow.com/a/4353844/5717099). – morido Jan 24 '16 at 09:58
  • @morido "In that case it is better to use usort with a comparison function that takes both fields into account, but if you can't do that then use the function below", but good points. Thanks for sharing. – Michael Jan 24 '16 at 10:08
1

It is easier to rewrite this way:

usort($order_list, function($v1, $v2) { return $v1[0] - $v2[0]; });

Or it is very convenient to sort arrays with sorted function from Nspl:

use function \nspl\a\sorted;
use function \nspl\op\itemGetter;

$sortedOrders = sorted($order_list, itemGetter(0));
Ihor Burlachenko
  • 4,689
  • 1
  • 26
  • 25