1

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

1 Answer 1

3

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 ] ]

Sign up to request clarification or add additional context in comments.

2 Comments

This does exactly what I want so many thanks. Please could you explain the significance of 9999 ($posA = 9999, $posB = 9999) as I'm not sure why that's used?
@Andy I'm just using fake values here so that the comparison works. As example, if the first two 1 will be compared, both will use the fake value of 9999. 9999 - 9999 = 0, so the order will remain at it is. It's possible that this could be cut off with remaining the same functionality, haven't tested that one to be honest.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.