У меня есть такой массив:
[
['array-5', 0],
['array-4', 0],
['array-1',-1],
['array-3', 2],
['array-2', 3]
]
Я хочу отсортировать это в PHP, чтобы отрицательные числа располагались перед положительными числами, и если знак тот же, величина (более отрицательная или более положительная) имеет приоритет.
Для приведенного выше примера желаемый результат будет таким:
[
['array-1',-1],
['array-2', 3],
['array-3', 2],
['array-4', 0],
['array-5', 0]
]
Если у $data
есть ваш вклад, вы можете вызвать usort
следующим образом:
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);
});
После того, как это будет выполнено, $data
будет иметь желаемый порядок.
не работает для чисел меньше 1 и больше 0, например 0,5
О, у вас есть дробные числа... см. обновление.
Сначала отсортируйте по минусам, а затем по убыванию абсолютного значения.
Код: (Демо)
usort(
$array,
fn($a, $b) => [$b[1] < 0, abs($b[1])]
<=>
[$a[1] < 0, abs($a[1])]
);
Или отделите вызовы abs()
в качестве второй/запасной оценки: (Demo)
usort(
$array,
fn($a, $b) => ($b[1] < 0 <=> $a[1] < 0)
?: (abs($b[1]) <=> abs($a[1]))
);
Возможно, более эффективным, но менее кратким было бы изолировать абсолютные значения, вызывая abs()
для каждого значения только один раз.
Код: (Демо)
$notNegs = [];
$absVals = [];
foreach ($array as [1 => $v]) {
$abs = abs($v);
$absVals[] = $abs;
$notNegs[] = $v === $abs;
}
array_multisort($notNegs, $absVals, SORT_DESC, $array);
Смотрите usort()