2010-10-12 4 views
3

Я пытаюсь заставить некоторую логику отображения вести себя и оставаться там, где она есть, и код превратился в интересную небольшую проблему, для которой было бы неплохо сделать общее решение.Группировка 2D-массива в соответствии с его значениями

Не стесняйтесь, это похоже на стену с текстом, но я попытался отформатировать ее с помощью простых примерных данных, чтобы это было понятно после быстрого проскальзывания.

Если по какой-то причине все это ужасная идея, мне нужно сообщить, прежде чем я создам оскорбление богов.

Начиная с данными, как это, например:

$data = array(

    array(
     'name' => 'Dave', 
     'age' => '21', 
     'city' => 'New York', 
    ), 
    array(
     'name' => 'Mike', 
     'age' => '19', 
     'city' => 'Chicago', 
    ), 
    array(
     'name' => 'John', 
     'age' => '21', 
     'city' => 'Chicago', 
    ), 
    array(
     'name' => 'Matt', 
     'age' => '19', 
     'city' => 'New York', 
    ), 
    array(
     'name' => 'Luke', 
     'age' => '21', 
     'city' => 'New York', 
    ), 

); 

С массивом ключевых имен, по которым группировки данных, таких как

$groups = array('city', 'age);

Данные, а затем становится:

$data = array(

    'New York' => array(
     '21' => array(
      array(
       'name' => 'Dave', 
       'age' => '21', 
       'city' => 'New York', 
      ), 
      array(
       'name' => 'Luke', 
       'age' => '21', 
       'city' => 'New York', 
      ), 
     ), 
     '19' => array(
      array(
       'name' => 'Matt', 
       'age' => '19', 
       'city' => 'New York', 
      ), 
     ), 
    ), 
    'Chicago' => array(
     '19' => array(
      array(
       'name' => 'Mike', 
       'age' => '19', 
       'city' => 'Chicago', 
      ), 
     ), 
     '21' => array(
      array(
       'name' => 'John', 
       'age' => '21', 
       'city' => 'Chicago', 
      ), 
     ), 
    ), 
); 

Когда я говорю «общее решение», я имею в виду, что я пытаюсь чтобы сделать что-то, что может группировать вещи на любой уровень вложенности, в зависимости от того, сколько имен ключей вы просите, чтобы они группировались.

Это похоже на проблему, которую я мог бы решить мгновенно, если бы я просто знал случайный эзотерический бит синтаксиса PHP. Какие-либо предложения? Я постараюсь это обновить, если я выясню это в то же время.

ответ

4
function group_array($arr, $fields) { 

    if(empty($fields) || !is_array($fields)) { 
     return $arr; 
    } 

    $newarr = array(); // so that we always return an array 
    $field = array_shift($fields); 

    foreach($arr as $val) { 
     $newarr[$val[$field]][] = $val; 
    } 

    foreach(array_keys($newarr) as $key) { 
     // Since we shifted one field off before, this groups by the remaining 
     $newarr[$key] = group_array($newarr[$key], $fields); 
    } 

    return $newarr; 
} 
+0

Черт, это именно то, о чем я говорю. Я видел твою маленькую ниндзя, чтобы остановить бесконечную рекурсию, хороший! Буквально единственное, что нужно было изменить, чтобы этот прогон был для => foreach, и это было сделано. Это означает, что вы даже не проверяли это, чтобы уловить синтаксическую ошибку, и фактическая сложная часть была первой в первый раз. Я в страхе. – Henry

+0

Хе, я работал с Python в последнее время, поэтому забыл сделать их «foreach». Исправлено. – Amber

0

Первоначально я пытаюсь сортировать массивы объектов таким образом, так как я собирался написать это в любом случае, вот один, который работает на объектах, даже если это немного Hacky идея

function group_objects($array, $fields) 
{ 
    if (empty($fields) || !is_array($fields)) { 
     return $array; 
    } 

    $newArray = array(); 
    $field = array_shift($fields); 

    foreach ($array as $object) { 
     $key = call_user_func(array($object, 'get' . ucwords($field))); 
     $newArray[$key][] = $object; 
    } 

    foreach (array_keys($newArray) as $key) { 
     $newArray[$key] = group_objects($newArray[$key], $fields); 
    } 

    return $newArray; 
} 
3

Я знаю, что это старый, но хотел опубликовать решение для других, когда они приходят к нему.

foreach($data as $row) { 
    $data_array[$row['city']][] = $row; 
} 
Смежные вопросы