Reputation: 2281
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.
Upvotes: 0
Views: 126
Reputation: 47894
It will be most direct/performant to build two flat arrays from the attribute keys and values then use array_multisort()
-- this involves no iterated function calls.
[..]
syntax in the first foreach()
is a technique called "array destructuring" and allows you to isolate only the data that you need within the body of the loop.[]
syntax in the nested foreach()
signature pushes keys and values into the output arrays.break
condition ensures that we never push more than the first element from each attribute subarray into the result array.Code: (Demo)
foreach ($array as ['attributes' => $attr]) {
foreach ($attr as $keys[] => $values[]) {
break;
}
}
array_multisort($keys, $values, $array);
var_export($array);
Upvotes: 0
Reputation: 54831
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]);
}
});
Upvotes: 1