Andy
Andy

Reputation: 5395

PHP - Sort array by subarray value based on a second array

I've done some research including going through PHP Sort Array By SubArray Value but this is a variation:

I have an array as follows:

$data = 
[
 0 => [
    'id' => (int) 5,
    'name' => 'Foo',
    'group_id' => (int) 1,
 ],
 1 => [
    'id' => (int) 6,
    'name' => 'Bar',
    'group_id' => (int) 1,
 ],
 2 => [
    'id' => (int) 8,
    'name' => 'Baz',
    'group_id' => (int) 7,
 ],
 3 => [
    'id' => (int) 9,
    'name' => 'ABC',
    'group_id' => (int) 2,
 ],
 4 => [
    'id' => (int) 10,
    'name' => 'DEF',
    'group_id' => (int) 65,
 ]
];

I also have an array second array of group_id's that are relevant to a search a user has performed:

$gids = [7, 65];

What I want to do is order $data by group_id based on the values inside $gids. So the order of $data should become:

 0 => [
    'id' => (int) 8,
    'name' => 'Baz',
    'group_id' => (int) 7,
 ],
 1 => [
    'id' => (int) 10,
    'name' => 'DEF',
    'group_id' => (int) 65,
 ]
 2 => [
    'id' => (int) 5,
    'name' => 'Foo',
    'group_id' => (int) 1,
 ],
 3 => [
    'id' => (int) 6,
    'name' => 'Bar',
    'group_id' => (int) 1,
 ],
 4 => [
    'id' => (int) 9,
    'name' => 'ABC',
    'group_id' => (int) 2,
 ],

Note that once the $gids array has been taken into account, the group_id of the remaining items in $data is numerical (ascending order in this case: 1, 1, 2).

I understand it's possible to use usort and an anonymous function, e.g.

 usort($data, function ($gids) {

 });

However, I don't understand what to write inside this function to perform ordering in this way? My initial thought was to do a foreach($gids) followed by a foreach($data) and compare the group_id value. But I don't know what to do in terms of modifying $data so that it reorders.

Please can someone help?

Equally, if there is already a post which explains how to do this please let me know, because I couldn't find one on here. The original link simply bases ordering numerically, not on a second array ($gids equivalent).

Using PHP 7.1.0

Upvotes: 1

Views: 70

Answers (1)

KhorneHoly
KhorneHoly

Reputation: 4766

This should do the trick

usort($data, function($a, $b) use ($gids)
{
    $posA = array_search($a['group_id'], $gids);
    if ($posA === false) {
        $posA = 9999;
    }

    $posB = array_search($b['group_id'], $gids);
    if ($posB === false) {
        $posB = 9999;
    }

    return $posA - $posB;
});

If found in the array of $gids, the sorting of $gids will be used, else the elements will stay in the order they're given in.

The return I'm getting is the following:

array:5 [▼ 0 => array:3 [▼ "id" => 8 "name" => "Baz" "group_id" => 7 ] 1 => array:3 [▼ "id" => 10 "name" => "DEF" "group_id" => 65 ] 2 => array:3 [▼ "id" => 5 "name" => "Foo" "group_id" => 1 ] 3 => array:3 [▼ "id" => 6 "name" => "Bar" "group_id" => 1 ] 4 => array:3 [▼ "id" => 9 "name" => "ABC" "group_id" => 2 ] ]

Upvotes: 3

Related Questions