简体   繁体   中英

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.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 (Ie, "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 );
    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.

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',
  ),
);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM