phparrayssortingmultidimensional-arraycustom-sort

Sort a 2d array using cascading rules based on a flat array matching one of the rows


I need to sort the rows of a 2d array based on the corresponding associative values in another flat array. The flat array will always match one of the rows in the 2d array.

I want the first row in $array2 to match the flat array. After that, rows with a venue_id matching the venue_id in the flat array should be prioritized.

$array1 = [
    'id' => 50575,
    'name' => 'Funbox - Pirates and Princesses',
    'venue_id' => 3248,
];

$array2 = [
    [
        'id' => 53295,
        'name' => 'Funbox - Pirates and Princesses',
        'venue_id' => 2954,
    ],
    [
        'id' => 53323,
        'name' => 'Funbox - Pirates and Princesses',
        'venue_id' => 2954,
    ],
    [
        'id' => 53391,
        'name' => 'Funbox - Pirates and Princesses',
        'venue_id' => 2954,
    ],
    [
        'id' => 53402,
        'name' => 'Funbox - Pirates and Princesses',
        'venue_id' => 2954,
    ],
    [
        'id' => 57130,
        'name' => 'Funbox - Pirates and Princesses',
        'venue_id' => 2980,
    ],
    [
        'id' => 57142,
        'name' => 'Funbox - Pirates and Princesses',
        'venue_id' => 3248,
    ],
    [
        'id' => 50575,
        'name' => 'Funbox - Pirates and Princesses',
        'venue_id' => 3248,
    ],
    [
        'id' => 50601,
        'name' => 'Funbox - Pirates and Princesses',
        'venue_id' => 3248,
    ],
    [
        'id' => 56113,
        'name' => 'Funbox - Pirates and Princesses',
        'venue_id' => 2882,
    ],
];

Desired result:

Array
    (
        [6] => Array
            (
                [id] => 50575
                [name] => Funbox - Pirates and Princesses
                [venue_id] => 3248
            )
        [5] => Array
            (
                [id] => 57142
                [name] => Funbox - Pirates and Princesses
                [venue_id] => 3248
            )
        [7] => Array
            (
                [id] => 50601
                [name] => Funbox - Pirates and Princesses
                [venue_id] => 3248
            )
        [0] => Array
            (
                [id] => 53295
                [name] => Funbox - Pirates and Princesses
                [venue_id] => 2954
            )
    
        [1] => Array
            (
                [id] => 53323
                [name] => Funbox - Pirates and Princesses
                [venue_id] => 2954
            )
    
        [2] => Array
            (
                [id] => 53391
                [name] => Funbox - Pirates and Princesses
                [venue_id] => 2954
            )
    
        [3] => Array
            (
                [id] => 53402
                [name] => Funbox - Pirates and Princesses
                [venue_id] => 2954
            )
    
        [4] => Array
            (
                [id] => 57130
                [name] => Funbox - Pirates and Princesses
                [venue_id] => 2980
            )
        [8] => Array
            (
                [id] => 56113
                [name] => Funbox - Pirates and Princesses
                [venue_id] => 2882
            )
    )

Solution

  • You can sort it to your example order using usort.

    function cmp($a, $b) {
      return $b["venue_id"] - $a["venue_id"];
    }
    
    usort($array2,"cmp"); 
    

    All this does is sort descending by venue_id. So all arrays with the same venue_id will be grouped, with the highest venue_id at the top. It is a bit unclear from your answer if you wanted something else.

    Edit: I have given this a bit more thought and come up with a function that should do what I think you're asking for. It's not perfect, but it should work.

    function customSort($array1,$array2) {
        global $primaryVenue_id;
        $primaryVenue_id = $array1["venue_id"];
        function cmp($a, $b) {
            global $primaryVenue_id;
            if ($a["venue_id"] == $primaryVenue_id) return -1;
            elseif ($b["venue_id"] == $primaryVenue_id) return 1;
            else return $b["venue_id"] - $a["venue_id"];
        }
    
        usort($array2, "cmp");
    
        unset($primaryVenue_id);
    
        return $array2;
    }
    

    Basically if you call the function customSort($array1,$array2) then it will return $array2, with all subarrays containing the same venue_id as $array1 first, followed by the rest descending order of id.