按内部键对数组元素进行分组

时间:2011-07-26 11:17:43

标签: php arrays sorting multidimensional-array

我在Google和SO上寻找解决方案,但现在已经很晚了,如果我遗漏了一些非常明显的东西,那就道歉了。

在PHP中,我有一个数组设置$rooms,如下所示:

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
  )
)

我想用相同的level键对条目进行分组(即,“将它们排序,以便它们在一起”)。但是,我还需要level组按以下顺序排列:1,n / a,2,3,4,(和on),U,L,B

我想我需要使用uasort();,但我无法绕过这些例子。

有任何帮助吗?非常感谢!

5 个答案:

答案 0 :(得分:4)

尝试:

$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);

答案 1 :(得分:3)

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);
    }
});

或者:

$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);
});

答案 2 :(得分:1)

这应该可以帮助你解决问题

http://www.firsttube.com/read/sorting-a-multi-dimensional-array-with-php/

如果您尝试按“级别”进行排序,那么这样的事情就可以满足您的需求(根据您的选择进行一些小调整)

$levelsort = subval_sort($rooms,'level'); 
print_r($levelsort );

答案 3 :(得分:1)

    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");

如果您想使用usort,那么这是针对您的案例的自定义排序解决方案。它将根据您描述的顺序对房间进行分类。

答案 4 :(得分:1)

使用array_reduceuksort可以在一对匿名函数的帮助下轻松完成此操作:

// 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);

我使用此示例数据集进行测试:

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