$unresponsives = [
[
"Customer",
"172.52.46.75",
"2022-04-01 16:20:45",
"1817",
"nxlog",
"2327.02 Hours"
],
[
"Customer",
"172.25.89.45",
"2022-04-01 16:20:45",
"1817",
"nxlog",
"2327.02 Hours"
],
[
"Customer",
"172.19.10.94",
"2022-04-01 16:20:45",
"1817",
"nxlog",
"2327.02 Hours"
]]
This is an example from my array of arrays. I want to sort the arrays inside by their fifth element (hours) in descending order. I am able to achieve this with usort but in the array there are also arrays with the string "Undefined" as their fifth value. Example below:
[
"PreProd",
"178.18.15.12",
"\/",
"1502",
"iis",
"Undefined"
]
Currently they are listed at the bottom of the array after the sorting is done. I instead want them to be listed in the beginning of the array. So first arrays with undefined ones and then the rest in descending order. How can I achieve this?
Below is the usort function that I use:
usort($unresponsives, function ($unresponsive1, $unresponsive2) {
return floatval($unresponsive2[5]) <=> floatval($unresponsive1[5]);
});
array_multisort
Approach - Example https://3v4l.org/SuJQXFor a slightly more complex approach that allows fine-grained control of the sorting as desired. Use array_column
to retrieve the hours. Use array_keys
on the hours to determine the filtered value positions and iterate over the positions to assign them as a numeric value. Then array_multisort
can be used with the desired flags to sort the resulting arrays.
$hours = array_column($unresponsives, 5);
if ($undefined = array_keys($hours, 'Undefined')) {
$hours = array_replace($hours, array_fill_keys($undefined, PHP_INT_MAX));
}
array_multisort($hours, SORT_DESC, SORT_NUMERIC, $unresponsives);
Result
var_export($unresponsives);
array (
0 =>
array (
0 => 'Customer',
1 => '172.19.10.94',
2 => '2022-04-01 16:20:45',
3 => '1817',
4 => 'nxlog',
5 => 'Undefined',
),
1 =>
array (
0 => 'Customer',
1 => '172.25.89.45',
2 => '2022-04-01 16:20:45',
3 => '1817',
4 => 'nxlog',
5 => 'Undefined',
),
2 =>
array (
0 => 'Customer',
1 => '172.52.46.75',
2 => '2022-04-01 16:20:45',
3 => '1817',
4 => 'nxlog',
5 => '2328.02 Hours',
),
3 =>
array (
0 => 'Customer',
1 => '172.19.10.94',
2 => '2022-04-01 16:20:45',
3 => '1817',
4 => 'nxlog',
5 => '2324.02 Hours',
),
4 =>
array (
0 => 'Customer',
1 => '172.19.10.94',
2 => '2022-04-01 16:20:45',
3 => '1817',
4 => 'nxlog',
5 => '2322.02 Hours',
),
)
Ascending Numeric Sorting
To change the sort order to SORT_ASC
swap out PHP_INT_MAX
for PHP_INT_MIN
, depending on where in the array you want the filtered value to reside.
$hours = array_column($unresponsives, 5);
if ($undefined = array_keys($hours, 'Undefined')) {
$hours = array_replace($hours, array_fill_keys($undefined, PHP_INT_MIN));
}
array_multisort($hours, SORT_ASC, SORT_NUMERIC, $unresponsives);
Result
var_export($unresponsives);
array (
0 =>
array (
0 => 'Customer',
1 => '172.19.10.94',
2 => '2022-04-01 16:20:45',
3 => '1817',
4 => 'nxlog',
5 => 'Undefined',
),
1 =>
array (
0 => 'Customer',
1 => '172.25.89.45',
2 => '2022-04-01 16:20:45',
3 => '1817',
4 => 'nxlog',
5 => 'Undefined',
),
2 =>
array (
0 => 'Customer',
1 => '172.19.10.94',
2 => '2022-04-01 16:20:45',
3 => '1817',
4 => 'nxlog',
5 => '2322.02 Hours',
),
3 =>
array (
0 => 'Customer',
1 => '172.19.10.94',
2 => '2022-04-01 16:20:45',
3 => '1817',
4 => 'nxlog',
5 => '2324.02 Hours',
),
4 =>
array (
0 => 'Customer',
1 => '172.52.46.75',
2 => '2022-04-01 16:20:45',
3 => '1817',
4 => 'nxlog',
5 => '2328.02 Hours',
),
)
usort
Approach - Example https://3v4l.org/Uoml6The same methodology of assigning the filtered value as a numeric value can be applied to usort
by manipulating the compared values of the desired filtered value(s) in a conditional, which will only be used to sort the array.
Descending Order
function compd($a, $b)
{
/*
# Condensed Syntax
return ('Undefined' === $b[5] ? PHP_INT_MAX : floatval($b[5])) <=> ('Undefined' === $a[5] ? PHP_INT_MAX : floatval($a[5]));
*/
$v1 = $a[5];
$v2 = $b[5];
if ('Undefined' === $v1) {
$v1 = PHP_INT_MAX;
}
if ('Undefined' === $v2) {
$v2 = PHP_INT_MAX;
}
return floatval($v2) <=> floatval($v1);
}
usort($unresponsives, 'compd');
Ascending Order
As with the array_multisort
approach change the sort order by swapping PHP_INT_MAX
with PHP_INT_MIN
but also swap the $b[5] <=> $a[5]
comparison with $a[5] <=> $b[5]
to sort the values in ascending order.
function compa($a, $b)
{
/*
# Condensed Syntax
return ('Undefined' === $a[5] ? PHP_INT_MIN : floatval($a[5])) <=> ('Undefined' === $b[5] ? PHP_INT_MIN : floatval($b[5]));
*/
$v1 = $a[5];
$v2 = $b[5];
if ('Undefined' === $v1) {
$v1 = PHP_INT_MIN;
}
if ('Undefined' === $v2) {
$v2 = PHP_INT_MIN;
}
return floatval($v1) <=> floatval($v2);
}
usort($unresponsives, 'compa');