Luna
Luna

Reputation: 11

sorting with uasort (multiple conditions)

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

Upvotes: 0

Views: 561

Answers (2)

jspit
jspit

Reputation: 7703

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)

Upvotes: 2

RiggsFolly
RiggsFolly

Reputation: 94672

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

});

Upvotes: 0

Related Questions