0

I'd like to use uasort to sort a multidimensional array. The array looks like this:

Array
(
    [0] => Array
        (
            [0] => 1612134001
            [1] => 1
            [2] => 'a'
        )

    [1] => Array
        (
            [0] => 1612134000
            [1] => 1
            [2] => 'b'
        )

    [2] => Array
        (
            [0] => 1612171201
            [1] => 0
            [] => 'c'
        )

    [3] => Array
        (
            [0] => 1612171200
            [1] => 0
            [] => 'd'
        )

    [4] => Array
        (
            [0] => 1612220400
            [1] => 1
            [2] => 'e'
        )
)

I expected output should look like this (sort timestamp asc [0] but if [1] is 0 put it above, but still consider the timestamp):

Array
(
    [0] => Array
        (
            [0] => 1612171200
            [1] => 0
            [] => 'd'
        )
    [0] => Array
        (
            [0] => 1612171201
            [1] => 0
            [] => 'c'
        )
    [1] => Array
        (
            [0] => 1612134000
            [1] => 1
            [2] => 'b'
        )

    [2] => Array
        (
            [0] => 1612134001
            [1] => 1
            [2] => 'a'
        )

    [3] => Array
        (
            [0] => 1612220400
            [1] => 1
            [2] => 'e'
        )
)

I tried uasort but they overwrite each other. Is it possible to do it in one uasort? I couldn't find anything about it.

  uasort($array, function ($a, $b) {
    return $a[0] - $b[0];
  });
  
  uasort($array, function ($a, $b) {
    return $a[1] - $b[1];
  });
Luna
  • 11
  • 2
  • Does this answer your question? [How can I sort arrays and data in PHP?](https://stackoverflow.com/questions/17364127/how-can-i-sort-arrays-and-data-in-php) – El_Vanja Jan 26 '21 at 16:36
  • Search for a section titled "Sorting by multiple fields" in the linked duplicate. – El_Vanja Jan 26 '21 at 16:36
  • @El_Vanja thank you for the link. I've already taken a look at it but I couldn't figure it out :( – Luna Jan 26 '21 at 16:42
  • Have you tried writing anything like it? If so, can you share the effort and explain how it fails? The code you show in the question performs two separate sorts. – El_Vanja Jan 26 '21 at 16:48
  • @El_Vanja I tried (order isn't correct, timestamps are not as). I would really appreciate it, if you can give me the if statement for my issue. if (($a[1] - $b[0]) > 0) { return $a[0] - $b[0]; } return $a[1] - $b[1]; – Luna Jan 26 '21 at 17:11
  • That condition is wrong (for one, it doesn't even compare the same data, you take `[1]` from `$a`, but take `[0]` from `$b`). Change it to `if ($a[1] === $b[1])` and it should be fine. – El_Vanja Jan 26 '21 at 17:17
  • @El_Vanja works like a charm. thank you!! and sorry for my late reply. – Luna Jan 27 '21 at 15:17

2 Answers2

2

It should be sorted in ascending order according to index 1 and then in ascending order according to index 0 (timestamp). The 'spaceship' operator <=> and the 'Elvis' operator ?: are very useful for a smart solution.

$in = [
    [1612134001, 1, 'a'],
    [1612134000, 1, 'b'],
    [1612171201, 0, 'c'],
    [1612171200, 0, 'd'],
    [1612220400, 1, 'e'],
];

//sort
usort($in, function ($a, $b) {
  return $a[1] <=> $b[1]  //first 
      ?: $a[0] <=> $b[0]  //second
  ;}
);

//Test
$expected = [
  [1612171200, 0, 'd'],
  [1612171201, 0, 'c'],
  [1612134000, 1, 'b'],
  [1612134001, 1, 'a'],   
  [1612220400, 1, 'e'],
];

var_dump($in === $expected);  //bool(true)
jspit
  • 7,276
  • 1
  • 9
  • 17
0

After a little testing this seems to work

$in = [
    [1612134001, 1, 'd'],
    [1612134000, 1, 'c'],
    [1612171201, 0, 'b'],
    [1612171200, 0, 'a'],
    [1612220400, 1, 'e'],
    [1612133999, 1, '??'],
];


uasort($in, function ($a, $b) {
    if ($a[1] == $b[1] && $a[0] == $b[0]) {
        return 0; 
    }
    if ($a[1] < $b[1]){
        return -1;
    }else if ($a[0] < $b[0] && $a[1] == $b[1]) {
        return -1;
    } else {
        return 1;
    }

});
RiggsFolly
  • 93,638
  • 21
  • 103
  • 149