PHP Sort Array By SubArray Value
I have the following array structure:
Array
(
[0] => Array
(
[configuration_id] => 10
[id] => 1
[optionNumber] => 3
[optionActive] => 1
[lastUpdated] => 2010-03-17 15:44:12
)
[1] => Array
(
[configuration_id] => 9
[id] => 1
[optionNumber] => 2
[optionActive] => 1
[lastUpdated] => 2010-03-17 15:44:12
)
[2] => Array
(
[configuration_id] => 8
[id] => 1
[optionNumber] => 1
[optionActive] => 1
[lastUpdated] => 2010-03-17 15:44:12
)
)
What is the best way to order the array in an incremental way, based on the optionNumber
?
So the results look like:
Array
(
[0] => Array
(
[configuration_id] => 8
[id] => 1
[optionNumber] => 1
[optionActive] => 1
[lastUpdated] => 2010-03-17 15:44:12
)
[1] => Array
(
[configuration_id] => 9
[id] => 1
[optionNumber] => 2
[optionActive] => 1
[lastUpdated] => 2010-03-17 15:44:12
)
[2] => Array
(
[configuration_id] => 10
[id] => 1
[optionNumber] => 3
[optionActive] => 1
[lastUpdated] => 2010-03-17 15:44:12
)
)
Solution 1:
Use usort
.
function cmp_by_optionNumber($a, $b) {
return $a["optionNumber"] - $b["optionNumber"];
}
...
usort($array, "cmp_by_optionNumber");
In PHP ≥5.3, you should use an anonymous function instead:
usort($array, function ($a, $b) {
return $a['optionNumber'] - $b['optionNumber'];
});
Note that both code above assume $a['optionNumber']
is an integer. Use @St. John Johnson's solution if they are strings.
In PHP ≥7.0, use the spaceship operator <=>
instead of subtraction to prevent overflow/truncation problems.
usort($array, function ($a, $b) {
return $a['optionNumber'] <=> $b['optionNumber'];
});
Solution 2:
Use usort
usort($array, 'sortByOption');
function sortByOption($a, $b) {
return strcmp($a['optionNumber'], $b['optionNumber']);
}
Solution 3:
I used both solutions by KennyTM and AJ Quick and came up with a function that can help in this issue for many cases like using ASC or DESC sorting or preserving keys or if you have objects as children of array.
Here is this function (works for PHP7 and higher because of spaceship operator):
/**
* @param array $array
* @param string $value
* @param bool $asc - ASC (true) or DESC (false) sorting
* @param bool $preserveKeys
* @return array
* */
function sortBySubValue($array, $value, $asc = true, $preserveKeys = false)
{
if ($preserveKeys) {
$c = [];
if (is_object(reset($array))) {
foreach ($array as $k => $v) {
$b[$k] = strtolower($v->$value);
}
} else {
foreach ($array as $k => $v) {
$b[$k] = strtolower($v[$value]);
}
}
$asc ? asort($b) : arsort($b);
foreach ($b as $k => $v) {
$c[$k] = $array[$k];
}
$array = $c;
} else {
if (is_object(reset($array))) {
usort($array, function ($a, $b) use ($value, $asc) {
return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
});
} else {
usort($array, function ($a, $b) use ($value, $asc) {
return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
});
}
}
return $array;
}
Usage:
sortBySubValue($array, 'optionNumber', true, false);
Edit
The first part can be rewritten using uasort()
and the function will be shorter (works for PHP7 and higher because of spaceship operator):
/**
* @param array $array
* @param string $value
* @param bool $asc - ASC (true) or DESC (false) sorting
* @param bool $preserveKeys
* @return array
* */
function sortBySubValue($array, $value, $asc = true, $preserveKeys = false)
{
if (is_object(reset($array))) {
$preserveKeys ? uasort($array, function ($a, $b) use ($value, $asc) {
return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
}) : usort($array, function ($a, $b) use ($value, $asc) {
return $a->{$value} == $b->{$value} ? 0 : ($a->{$value} <=> $b->{$value}) * ($asc ? 1 : -1);
});
} else {
$preserveKeys ? uasort($array, function ($a, $b) use ($value, $asc) {
return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
}) : usort($array, function ($a, $b) use ($value, $asc) {
return $a[$value] == $b[$value] ? 0 : ($a[$value] <=> $b[$value]) * ($asc ? 1 : -1);
});
}
return $array;
}
Solution 4:
Using array_multisort(), array_map()
array_multisort(array_map(function($element) {
return $element['optionNumber'];
}, $array), SORT_ASC, $array);
print_r($array);
DEMO
Solution 5:
The keys are removed when using a function like the ones above. If the keys are important, the following function would maintain it... but foreach loops are pretty inefficient.
function subval_sort($a,$subkey) {
foreach($a as $k=>$v) {
$b[$k] = strtolower($v[$subkey]);
}
asort($b);
foreach($b as $key=>$val) {
$c[$key] = $a[$key];
}
return $c;
}
$array = subval_sort($array,'optionNumber');
Use arsort instead of asort if you want from high to low.
Code credit: http://www.firsttube.com/read/sorting-a-multi-dimensional-array-with-php/