Reputation: 95
I have two arrays, one is a multidimensional array which holds information, the other is a simple array which holds values for the order I want the first array in.
For example, I want my first array to be ordered by ID, by the values in the second array.
$users array:
array(3) {
[0] => array(3) {
'id' => 1,
'name' => 'John Smith',
'email' => '[email protected]',
},
[2] => array(3) {
'id' => 2,
'name' => 'Jane Smith',
'email' => '[email protected]',
},
[0] => array(3) {
'id' => 3,
'name' => 'Jack Smith',
'email' => '[email protected]',
},
}
$order array:
array(3) {
[0] => '2',
[1] => '3',
[2] => '1',
}
What I would like the outcome of the sorted array to be:
array(3) {
[0] => array(3) {
'id' => 2,
'name' => 'Jane Smith',
'email' => '[email protected]',
},
[2] => array(3) {
'id' => 3,
'name' => 'Jack Smith',
'email' => '[email protected]',
},
[0] => array(3) {
'id' => 1,
'name' => 'John Smith',
'email' => '[email protected]',
},
}
So as you can see, I would like the array keys to be reindexed, so they are always sequential starting from 0, but for the values of each element in the $users array to be re ordered.
Upvotes: 2
Views: 3386
Reputation: 173
You can use usort to achieve this :
// the key order of each id
$orderIdKeys = array_flip($order);
usort($users, function ($u1, $u2) use ($orderIdKeys) {
// compare the keys of the ids in the $order array
return $orderIdKeys[$u1['id']] >= $orderIdKeys[$u2['id']] ? 1 : -1;
});
Then $users
should be ordered.
The usort here is comparing users based on the position ( which is $orderIdKeys[$u1['id']]
) of each user id in $order array, If the position of $u1['id']
is greater than the position of $u2['id']
the callback returns 1 which means $u2
should be placed before $u1
in the final ordered array
Upvotes: 1
Reputation: 3802
You can do this like this:
// Index users by ID
$users = array_combine(
array_column($users, 'id'),
$users
);
// Order the users
$users = array_map(function ($id) use ($users) {
return $users[$id];
}, $order);
Here I used array_combine()
function, that creates array by mapping given keys to values. For the keys I used all the id's in a sequential order (grabbed them with array_column()
).
Having an array in such form, I can loop over $order
array and grab the values from $users
array by index, that actually have the value of id
now.
Instead of looping with foreach
I used array_map()
function. If you have a collection (i.e. array) it is better to use higher order functions to process them. If you are a beginner it can be overwhelming, but you have to learn this, as this is the way things done nowadays.
Upvotes: 5
Reputation: 1795
I think that this should do the job:
$array = array(
array(
'id' => 2,
'name' => 'Jane Smith',
'email' => '[email protected]',
),
array(
'id' => 3,
'name' => 'Jack Smith',
'email' => '[email protected]',
),
array(
'id' => 1,
'name' => 'John Smith',
'email' => '[email protected]',
),
);
function cmp_by_optionNumber($a, $b) {
return $a["id"] - $b["id"];
}
usort($array, "cmp_by_optionNumber");
var_dump($array);
It will sort your main array by the values of the "id" keys in the subarrays.
Upvotes: -1