phparrayssortingmultidimensional-arrayarray-multisort

Sort multidimensional array by first element in specific 3rd level subarray -- sort by its key first, then by its value


I need to sort the rows of my multidimensional array by the first element of its subarray. Each row may have a dynamically named first element in its attribute subarray. I want to sort first by the first element's key, then by the value of the first element.

My input array looks like this:

$array = [
    [
        'tag' => 'meta',
        'type' => 'complete',
        'attributes' => ['property' => 'og:type', 'content' => 'website']
    ],
    [
        'tag' => 'meta',
        'type' => 'complete',
        'attributes' => ['name' => 'robots', 'content' => 'noindex, nofollow']
    ],
    [
        'tag' => 'meta',
        'type' => 'complete',
        'attributes' => ['name' => 'application', 'content' => 'My Application']
    ],
    [
        'tag' => 'meta',
        'type' => 'complete',
        'attributes' => ['http-equiv' => 'content-type', 'content' => 'text/html; charset=utf-8']
    ]
];

How I can sort it with array_multisort()?

Desired output:

Array
(
    [0] => Array
        (
            [tag] => meta
            [type] => complete
            [attributes] => Array
                (
                    [http-equiv] => content-type
                    [content] => text/html; charset=utf-8
                )
        )
    [1] => Array
        (
            [tag] => meta
            [type] => complete
            [attributes] => Array
                (
                    [name] => application
                    [content] => My Application
                )
        )
    [2] => Array
        (
            [tag] => meta
            [type] => complete
            [attributes] => Array
                (
                    [name] => robots
                    [content] => noindex, nofollow
                )
        )
    [3] => Array
        (
            [tag] => meta
            [type] => complete
            [attributes] => Array
                (
                    [property] => og:type
                    [content] => website
                )
        )
)

I am having some difficulty because the first column of attributes is unpredictably keyed.


Solution

  • usort with custom callback will look like:

    usort($arr, function($a, $b) {
       $aKeyFirst = array_key_first($a['attributes']);
       // fallback, php version < 7.3
       //$aKeyFirst = array_keys($a['attributes'])[0];
       
       $bKeyFirst = array_key_first($b['attributes']);
       // fallback, php version < 7.3
       //$bKeyFirst = array_keys($b['attributes'])[0];
       
       if ($aKeyFirst !== $bKeyFirst) {
           return strcmp($aKeyFirst, $bKeyFirst);
       } else {
           return strcmp($a['attributes'][$aKeyFirst], $b['attributes'][$bKeyFirst]);
       }
    });