Все,
У меня есть следующий массив и функция, которые создадут многомерный массив на основе определенных вами ключей массива. Для каждого атрибута, который вы передаете функции, он добавит другое измерение в массив. Подумайте об этом как о сортировке массива.
Предоставляемая функция отлично работает, но использует eval, мне было трудно найти функцию, которая была последовательной, и без нее не было ошибок.
Начнем с массива:
$array = array( array('name' => 'Person1', 'username' => 'username1', 'join_date' => 12233445566, 'state' => 'NJ'), array('name' => 'Person2', 'username' => 'username2', 'join_date' => 12233445566, 'state' => 'NJ'), array('name' => 'Person3', 'username' => 'username3', 'join_date' => 12233445996, 'state' => 'NY'), array('name' => 'Person4', 'username' => 'username4', 'join_date' => 12233445996, 'state' => 'NJ'), array('name' => 'Person5', 'username' => 'username5', 'join_date' => 12233445566, 'state' => 'NJ'), array('name' => 'Person6', 'username' => 'username6', 'join_date' => 12233445566, 'state' => 'NY'), array('name' => 'Person7', 'username' => 'username7', 'join_date' => 12233445776, 'state' => 'NY'), array('name' => 'Person8', 'username' => 'username8', 'join_date' => 12233445566, 'state' => 'NY'), array('name' => 'Person9', 'username' => 'username9', 'join_date' => 12233445996, 'state' => 'NJ'), );
Вот пример функции:
function createIndex($array, $index){ $index_array = array(); foreach($array as $result){ if(is_array($index)){ $key = '$index_array'; for($i=0;$i<=sizeof($index)-1;$i++){ $key .= "['{$result[$index[$i]]}']"; } $key .= "[]"; eval("$key = \$result;"); } else{ $index_array[$result[$index]] = $result; } } return $index_array; }
Функция вызова:
print_r(create_index($array, array('state', 'join_date')));
Желаемый результат:
Array ( [NJ] => Array ( [12233445566] => Array ( [0] => Array ( [name] => Person1 [username] => username1 [join_date] => 12233445566 [state] => NJ ) [1] => Array ( [name] => Person2 [username] => username2 [join_date] => 12233445566 [state] => NJ ) [2] => Array ( [name] => Person5 [username] => username5 [join_date] => 12233445566 [state] => NJ ) ) [12233445996] => Array ( [0] => Array ( [name] => Person4 [username] => username4 [join_date] => 12233445996 [state] => NJ ) [1] => Array ( [name] => Person9 [username] => username9 [join_date] => 12233445996 [state] => NJ ) ) ) [NY] => Array ( [12233445996] => Array ( [0] => Array ( [name] => Person3 [username] => username3 [join_date] => 12233445996 [state] => NY ) ) [12233445566] => Array ( [0] => Array ( [name] => Person6 [username] => username6 [join_date] => 12233445566 [state] => NY ) [1] => Array ( [name] => Person8 [username] => username8 [join_date] => 12233445566 [state] => NY ) ) [12233445776] => Array ( [0] => Array ( [name] => Person7 [username] => username7 [join_date] => 12233445776 [state] => NY ) ) ) )
Вопрос: Каковы способы, которыми вы могли бы победить выше, чтобы получить одни и те же результаты, образуют один и тот же массив? Мне любопытно посмотреть, как это сделают другие.
благодаря
Я придумал в основном то же решение, что и Райан, но я столкнулся с проблемами, когда ключ был int
… следовательно, typecasting для string
для ключа массива …
function createIndex($set, $indexes) { $return = array(); if(!is_array($indexes)){ $indexes = array($indexes); } foreach($set as $data){ $curr =& $return; foreach($indexes as $index){ $key = (string)$data[$index]; if(!is_array($curr[$key])){ $curr[$key] = array(); } $curr =& $curr[$key]; } $curr[] = $data; } return $return; }
Вот что я буду делать. Также обратите внимание, как вы можете перейти в $ index_array по ссылке. Я лично использую это в своем коде, поэтому я могу обрабатывать большие объемы данных в партиях и иногда удалять данные.
Это все о хранении переменных по ссылке:
function create_index($array, $indexes, &$index_array = array()) { if(!is_array($indexes)) $indexes = array($indexes); foreach($array as $result) { $object = &$index_array; foreach($indexes as $index){ if(!array_key_exists((string)$result[$index], $object)) { $object[(string)$result[$index]] = array(); } $object = &$object[(string)$result[$index]]; } $object[] = $result; } return $index_array; }
Затем, чтобы использовать его:
// You can use it like you did in your question: print_r(create_index($array, array('state', 'join_date'))); // Or you can process in chunks: $results = array(); while(/* store data from database in $array */) { create_index($array, array('state', 'join_date'), &$results); }
Используя ссылки, я смог придумать функцию ниже. Он отлично работает!
Он автоматически определит, существуют ли несколько листьев в конце дерева, и если да, то ветвь или сам лист. Кроме того, вы можете объединиться, используя аргумент $merge_classifier
. Это позволит вам объединить столбцы, например count
, которые будут добавлять значения вместе.
function createIndex($keys, Array $array, $merge_classifier = NULL, $return_array = array()) { if(is_string($keys)){ $tmp = $keys; $keys = array(); $keys[] = $tmp; } foreach($array as $result) { $object = &$return_array; foreach($keys as $index){ if(!array_key_exists($result[$index], $object)) { $object[$result[$index]] = array(); } $object = &$object[$result[$index]]; } if(!is_null($merge_classifier)){ $object = array_merge($result, array($merge_classifier => ($result[$merge_classifier] + $object[$merge_classifier]))); } else{ if(sizeof($object) > 0){ $object[] = $result; }else{ $object = $result; } } } return $return_array; }