Grouping array elements by interior key
I looked around for a solution, both on Google and SO, but it's pretty late, so apologies if I'm missing something really obvious.
In PHP, I have an array set up, $rooms
, such that it looks like:
Array
(
[0] => Array
(
[title] => Bedroom
[area] => 16.00
[length] => 4.00
[width] => 4.00
[level] => U
)
[1] => Array
(
[title] => Kitchen
[area] => 18开发者_StackOverflow社区.00
[length] => 2.00
[width] => 9.00
[level] => 1
)
[2] => Array
(
[title] => Basement
[area] => 32.00
[length] => 8.00
[width] => 4.00
[level] => 2
)
[3] => Array
(
[title] => Bathroom
[area] => 9.00
[length] => 3.00
[width] => 3.00
[level] => L
)
[3] => Array
(
[title] => Deck
[area] => 9.00
[length] => 3.00
[width] => 3.00
[level] => n/a
)
)
I'm wanting to group the entries with the same level
keys (I.e., "sort them so they're together"). However, I also need the level
groups to be in the following order: 1, n/a, 2, 3, 4, (and on), U, L, B
I figure I need to use uasort();, but I just can't wrap my head around the examples.
Any help? Many thanks!
Try with:
$data = array();
$output = array();
$levelSort = array('1', 'n/a', '2', '3', '4', '(and on)', 'U', 'L', 'B');
foreach ( $rooms as $room ) {
if ( empty($data[$room['level']]) ) {
$data[$room['level']] = array();
}
$data[$room['level']][] = $room;
}
foreach ( $levelSort as $level ) {
$levelData = !empty($data[$level]) ? $data[$level] : array();
$output = array_merge($output, $levelData);
}
var_dump($output);
usort($array, function ($a, $b) {
$a = $a['level'];
$b = $b['level'];
if ($a == $b) {
return 0;
} else if ($a == 1 && $b == 'n/a') {
return 1;
} else if ($b == 1 && $a == 'n/a') {
return -1;
} else if (is_numeric($a) && is_numeric($b)) {
return $b - $a;
} else if (is_numeric($a)) {
return 1;
} else if (is_numeric($b)) {
return -1;
} else {
static $order = array('U', 'L', 'B');
return array_search($b, $order) - array_search($a, $order);
}
});
Or:
$topFloor = array_reduce($array, function ($max, $a) { return max($max, (int)$a['level']); }, 0);
$order = array_merge(array(1, 'n/a'), range(2, max(2, $topFloor)), array('U', 'L', 'B'));
usort($array, function ($a, $b) use ($order) {
return array_search($b['level'], $order) - array_search($a['level'], $order);
});
This should help you out I think
http://www.firsttube.com/read/sorting-a-multi-dimensional-array-with-php/
If you are trying to order by "level" then something like this will do what you want (with a few small tweaks depending on your options)
$levelsort = subval_sort($rooms,'level');
print_r($levelsort );
This can be done easily with array_reduce
and uksort
, with the help of a couple anonymous functions:
// ORDERING FOR level VALUES:
$order = array('1', 'n/a', '2', '3', '4', '5', '6', '7', '8', 'U', 'L', 'B');
// GROUPING ITEMS BY level:
$result = array_reduce($input,
function($aggr, $val) {
$aggr[$val['level']][] = $val; return $aggr;
},
array());
// SORTING GROUPS BY level:
uksort($result, function($a, $b) use($order) {
return array_search($a, $order) - array_search($b, $order);
});
print_r($result);
I used this sample dataset for testing:
// SAMPLE DATA
$input = array (
0 =>
array (
'title' => 'Bedroom',
'area' => 16,
'length' => 4,
'width' => 4,
'level' => 'U',
),
1 =>
array (
'title' => 'Kitchen',
'area' => 18,
'length' => 2,
'width' => 9,
'level' => 1,
),
2 =>
array (
'title' => 'Basement',
'area' => 32,
'length' => 8,
'width' => 4,
'level' => 'L',
),
3 =>
array (
'title' => 'Bathroom',
'area' => 9,
'length' => 3,
'width' => 3,
'level' => 'L',
),
4 =>
array (
'title' => 'Deck',
'area' => 9,
'length' => 3,
'width' => 3,
'level' => 'n/a',
),
);
function cmp($a, $b) {
$letter_order = array('1', 'n/a', '2', '3', '4', '5', '6', '7', '8', 'U', 'L', 'B');
if ($a['level'] == $b['level']) {
return 0;
} else {
return (array_search($a['level'], $letter_order) < array_search($b['level'], $letter_order)) ? -1 : 1;
}
}
uasort($your_array, "cmp");
That is a custom sorting solution for your case if you want ot use uasort. It will sort the room according to the order described by you.
精彩评论