开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜