'PHP sort array of objects by two properties
I have an array
Array
(
[0] => stdClass Object
(
[tab_option_name_selector] => 2
[fieldtype] => notes
[order] => 12
)
[1] => stdClass Object
(
[tab_option_name_selector] => 2
[fieldtype] => notes
[order] => 8
)
[2] => stdClass Object
(
[tab_option_name_selector] => 1
[order] => 2
[fieldtype] => selectbox
)
[3] => stdClass Object
(
[tab_option_name_selector] => 2
[order] => 3
[fieldtype] => selectbox
)
)
I'm trying to get this usort function to work
function osort(&$array, $props)
{
if(!is_array($props))
$props = array($props => true);
$me = usort($array, function($a, $b) use ($props) {
foreach($props as $prop => $ascending)
{
if($a->$prop != $b->$prop)
{
if($ascending)
return $a->$prop > $b->$prop ? 1 : -1;
else
return $b->$prop > $a->$prop ? 1 : -1;
}
}
return -1; //if all props equal
});
print_r($props);
return ($me);
}
$tab = osort($objectArray, "tab_option_name_selector", "order");
so sorting by the tab then order.
$tab is empty - any ideas what I'm doing wrong?
Solution 1:[1]
Why the extra level of indirection and making things more confusing? Why not usort directly with usort($objectArray, "sortObjects");
using a sortObjects($a,$b)
function that does what any comparator does: return negative/0/positive numbers based on the input?
If the tabs differ, return their comparison, if they're the same, return the order comparison; done.
$array = array(
(object)array(
'tab_option_name_selector' => 2,
'fieldtype' => 'notes',
'order' => 12
),
(object)array(
'tab_option_name_selector' => 2,
'fieldtype' => 'notes',
'order' => 8
),
(object)array(
'tab_option_name_selector' => 1,
'order' => 2,
'fieldtype' => 'selectbox'
),
(object)array(
'tab_option_name_selector' => 2,
'order' => 3,
'fieldtype' => 'selectbox'
)
);
function compareTabAndOrder($a, $b) {
// compare the tab option value
$diff = $a->tab_option_name_selector - $b->tab_option_name_selector;
// and return it. Unless it's zero, then compare order, instead.
return ($diff !== 0) ? $diff : $a->order - $b->order;
}
usort($array, "compareTabAndOrder");
print_r($array);
Solution 2:[2]
Why don't you use array_multisort
? http://php.net/manual/de/function.array-multisort.php
$data = //your array
//Create independent arrays
foreach ($data as $row) {
foreach ($row as $key => $value){
${$key}[] = $value;
//Creates $tab_option_name_selector, $fieldtype and $order array
//in order to use them as independent arrays in array_multisort.
}
}
array_multisort($tab_option_name_selector, SORT_ASC, $order, SORT_ASC, $data);
//$data sorted as expected.
echo "<pre>";
print_r($data);
echo "</pre>";
Solution 3:[3]
An example for unlimited number of properties:
$data = [
(object)['volume' => '1', 'edition' => '1'],
(object)['volume' => '2', 'edition' => '1'],
(object)['volume' => '3', 'edition' => '10'],
(object)['volume' => '3', 'edition' => '50'],
(object)['volume' => '3', 'edition' => '20'],
(object)['volume' => '4', 'edition' => '3'],
];
// sorting list by properties
$sorting = ['volume' => SORT_DESC, 'edition' => SORT_ASC];
$arrays = [];
foreach ($sorting as $key => $sort) {
$column = array_column($data, $key);
if (!empty($column)) {
$arrays[] = $column;
$arrays[] = $sort;
}
}
if (!empty($arrays)) {
$arrays[] = $data;
if (!array_multisort(...$arrays)) {
var_dump('some error');
die();
}
// get last array, that is the sorted data
$data = ($arrays[array_key_last($arrays)]);
}
Example partially from php.net - array_multisort
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | |
Solution 3 | Aldo |