skip to Main Content

I have an array like this:

[
    ['array-5', 0],
    ['array-4', 0],
    ['array-1',-1],
    ['array-3', 2],
    ['array-2', 3]
]

I want to sort this in PHP so that negative numbers are ordered before positive numbers, and if the sign is the same, the magnitude (more negative or more positive) has precedence.

For the example above, the desired output would be:

[
    ['array-1',-1],
    ['array-2', 3],
    ['array-3', 2],
    ['array-4', 0],
    ['array-5', 0]
]

2

Answers


  1. If $data has your input, you can call usort like this:

    usort($data, function ($a, $b) {
        $res = ($b[1] < 0) - ($a[1] < 0);
        $diff = abs($b[1]) - abs($a[1]);
        return $res ? $res : ($diff > 0) - ($diff < 0);
    });
    

    After this has executed, $data will have the desired order.

    Login or Signup to reply.
  2. Sort by negatives first, then sort by absolute value descending.

    Code: (Demo)

    usort(
        $array,
        fn($a, $b) => [$b[1] < 0, abs($b[1])]
                      <=>
                      [$a[1] < 0, abs($a[1])]
    );
    

    Or separate the abs() calls as a second/fallback evaluation: (Demo)

    usort(
        $array,
        fn($a, $b) => ($b[1] < 0 <=> $a[1] < 0)
                      ?: (abs($b[1]) <=> abs($a[1]))
    );
    

    Perhaps more efficient but less concise would be to isolate absolute values by calling abs() on each value only once.

    Code: (Demo)

    $notNegs = [];
    $absVals = [];
    foreach ($array as [1 => $v]) {
        $abs = abs($v);
        $absVals[] = $abs;
        $notNegs[] = $v === $abs;
    }
    array_multisort($notNegs, $absVals, SORT_DESC, $array);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search