Вероятно, это вопрос новичка, но я уже давно просматриваю документацию и не могу найти никакого решения. Я подумал, что могу использовать сжатие для каждого измерения, а затем соединить эти строки вместе, str_split
чтобы создать новый простой массив. Однако я никогда не знаю, есть ли шаблон соединения также в значениях, и поэтому str_split
мои исходные значения могут сломаться.
Есть ли что-то вроде combine($array1, $array2)
массивов внутри многомерного массива?
php
arrays
multidimensional-array
Адриана
источник
источник
Ответы:
Использовать
array_walk_recursive
<?php $aNonFlat = array( 1, 2, array( 3, 4, 5, array( 6, 7 ), 8, 9, ), 10, 11 ); $objTmp = (object) array('aFlat' => array()); array_walk_recursive($aNonFlat, create_function('&$v, $k, &$t', '$t->aFlat[] = $v;'), $objTmp); var_dump($objTmp->aFlat); /* array(11) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> int(4) [4]=> int(5) [5]=> int(6) [6]=> int(7) [7]=> int(8) [8]=> int(9) [9]=> int(10) [10]=> int(11) } */ ?>
Протестировано с PHP 5.5.9-1ubuntu4.24 (cli) (построено: 16 марта 2018 г. 12:32:06)
источник
$objTmp
в этом примере) передаются по ссылке автоматически; массивы нет. Попробуйте использовать анонимную функцию ( php.net/manual/en/functions.anonymous.php ) вместоcreate_function
.This bug has been fixed in SVN.
array_values()
? Я вообще не вижу использования этой функции в ответе.$array = your array $result = call_user_func_array('array_merge', $array); echo "<pre>"; print_r($result);
ССЫЛКА: http://php.net/manual/en/function.call-user-func-array.php
Вот еще одно решение (работает с многомерным массивом):
function array_flatten($array) { $return = array(); foreach ($array as $key => $value) { if (is_array($value)){ $return = array_merge($return, array_flatten($value));} else {$return[$key] = $value;} } return $return; } $array = Your array $result = array_flatten($array); echo "<pre>"; print_r($result);
источник
$result = array_merge(...$array);
php.net/manual/en/…Это одна строка, СУПЕР простая в использовании:
$result = array(); array_walk_recursive($original_array,function($v) use (&$result){ $result[] = $v; });
Это очень легко понять внутри анонимной функции / закрытия.
$v
ценность вашего$original_array
.источник
// $array = your multidimensional array $flat_array = array(); foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $k=>$v){ $flat_array[$k] = $v; }
Также задокументировано: http://www.phpro.org/examples/Flatten-Array.html
источник
iterator_to_array()
к этому ответу устранит необходимость вforeach
цикле. Это может быть простая однострочная функция. (хотя и довольно длинная однострочная)Если у вас специально есть массив массивов, который не превышает одного уровня в глубину (вариант использования, который я нахожу обычным), вам может сойти с рук
array_merge
и оператор splat.<?php $notFlat = [[1,2],[3,4]]; $flat = array_merge(...$notFlat); var_dump($flat);
Вывод:
array(4) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> int(4) }
Оператор splat эффективно изменяет массив массивов на список массивов в качестве аргументов для
array_merge
.источник
$flat = array_merge( array_keys( $notFlat ), ...array_values( $notFlat ) );
В PHP 7 вы можете использовать генераторы и делегирование генератора (
yield from
) для сглаживания массива:function array_flatten_iterator (array $array) { foreach ($array as $value) { if (is_array($value)) { yield from array_flatten_iterator($value); } else { yield $value; } } } function array_flatten (array $array) { return iterator_to_array(array_flatten_iterator($array), false); }
Пример:
$array = [ 1, 2, [ 3, 4, 5, [ 6, 7 ], 8, 9, ], 10, 11, ]; var_dump(array_flatten($array));
http://3v4l.org/RU30W
источник
function flatten_array($array, $preserve_keys = 0, &$out = array()) { # Flatten a multidimensional array to one dimension, optionally preserving keys. # # $array - the array to flatten # $preserve_keys - 0 (default) to not preserve keys, 1 to preserve string keys only, 2 to preserve all keys # $out - internal use argument for recursion foreach($array as $key => $child) if(is_array($child)) $out = flatten_array($child, $preserve_keys, $out); elseif($preserve_keys + is_string($key) > 1) $out[$key] = $child; else $out[] = $child; return $out; }
источник
Другой метод из комментариев пользователей PHP (упрощенный) и здесь :
function array_flatten_recursive($array) { if (!$array) return false; $flat = array(); $RII = new RecursiveIteratorIterator(new RecursiveArrayIterator($array)); foreach ($RII as $value) $flat[] = $value; return $flat; }
Большим преимуществом этого метода является то, что он отслеживает глубину рекурсии, если вам это нужно при выравнивании.
Это выведет:
$array = array( 'A' => array('B' => array( 1, 2, 3)), 'C' => array(4, 5) ); print_r(array_flatten_recursive($array)); #Returns: Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 )
источник
Нерекурсивное решение (но разрушающее порядок):
function flatten($ar) { $toflat = array($ar); $res = array(); while (($r = array_shift($toflat)) !== NULL) { foreach ($r as $v) { if (is_array($v)) { $toflat[] = $v; } else { $res[] = $v; } } } return $res; }
источник
В PHP> = 5.3 и на основе ответа Люка М (первого) вы можете использовать такие закрытия, как это
array_walk_recursive($aNonFlat, function(&$v, $k, &$t){$t->aFlat[] = $v;}, $objTmp);
Мне это нравится, потому что мне не нужно заключать код функции в кавычки, как при использовании create_function ()
источник
objTemp
материалИспользование функций высшего порядка (примечание: я использую встроенные анонимные функции , появившиеся в PHP 5.3):
function array_flatten($array) { return array_reduce( $array, function($prev, $element) { if (!is_array($element)) $prev[] = $element; else $prev = array_merge($prev, array_flatten($element)); return $prev; }, array() ); }
источник
Новый подход, основанный на функции из предыдущего примера, переданной с помощью chaos, который исправляет ошибку перезаписи строковых ключей в многомассивах:
# Flatten a multidimensional array to one dimension, optionally preserving keys. # $array - the array to flatten # $preserve_keys - 0 (default) to not preserve keys, 1 to preserve string keys only, 2 to preserve all keys # $out - internal use argument for recursion function flatten_array($array, $preserve_keys = 2, &$out = array(), &$last_subarray_found) { foreach($array as $key => $child) { if(is_array($child)) { $last_subarray_found = $key; $out = flatten_array($child, $preserve_keys, $out, $last_subarray_found); } elseif($preserve_keys + is_string($key) > 1) { if ($last_subarray_found) { $sfinal_key_value = $last_subarray_found . "_" . $key; } else { $sfinal_key_value = $key; } $out[$sfinal_key_value] = $child; } else { $out[] = $child; } } return $out; } Example: $newarraytest = array(); $last_subarray_found = ""; $this->flatten_array($array, 2, $newarraytest, $last_subarray_found);
источник
/*consider $mArray as multidimensional array and $sArray as single dimensional array this code will ignore the parent array */ function flatten_array2($mArray) { $sArray = array(); foreach ($mArray as $row) { if ( !(is_array($row)) ) { if($sArray[] = $row){ } } else { $sArray = array_merge($sArray,flatten_array2($row)); } } return $sArray; }
источник
вы можете попробовать это:
function flat_an_array($a) { foreach($a as $i) { if(is_array($i)) { if($na) $na = array_merge($na,flat_an_array($i)); else $na = flat_an_array($i); } else $na[] = $i; } return $na; }
источник
Если вас устраивает потеря ключей массива, вы можете сгладить многомерный массив, используя рекурсивное закрытие в качестве обратного вызова, который использует array_values (), убедившись, что этот обратный вызов является параметром для array_walk (), как показано ниже.
<?php $array = [1,2,3,[5,6,7]]; $nu_array = null; $callback = function ( $item ) use(&$callback, &$nu_array) { if (!is_array($item)) { $nu_array[] = $item; } else if ( is_array( $item ) ) { foreach( array_values($item) as $v) { if ( !(is_array($v))) { $nu_array[] = $v; } else { $callback( $v ); continue; } } } }; array_walk($array, $callback); print_r($nu_array);
Единственным недостатком предыдущего примера является то, что он требует написания гораздо большего количества кода, чем следующее решение, которое использует array_walk_recursive () вместе с упрощенным обратным вызовом:
<?php $array = [1,2,3,[5,6,7]]; $nu_array = []; array_walk_recursive($array, function ( $item ) use(&$nu_array ) { $nu_array[] = $item; } ); print_r($nu_array);
Посмотреть живой код
Этот пример кажется предпочтительным по сравнению с предыдущим, поскольку он скрывает подробности извлечения значений из многомерного массива. Конечно, итерация происходит, но повлечет ли она за собой рекурсию или структуру (ы) управления, вы узнаете только из просмотра array.c . Поскольку функциональное программирование фокусируется на вводе и выводе, а не на мелочах получения результата, конечно, можно не беспокоиться о том, как происходит закулисная итерация, пока перспективный работодатель не задаст такой вопрос.
источник
Я нашел простой способ преобразовать многоуровневый массив в один. Я использую функцию http_build_query, которая преобразует массив в строку url. Затем разделите строку с помощью explode и декодируйте значение.
Вот образец.
$converted = http_build_query($data); $rows = explode('&', $converted); $output = array(); foreach($rows AS $k => $v){ list($kk, $vv) = explode('=', $v); $output[ urldecode($kk) ] = urldecode($vv); } return $output;
источник
Извините за некробампинг, но ни один из предоставленных ответов не сделал того, что я интуитивно понял как «выравнивание многомерного массива». А именно этот случай:
[ 'a' => [ 'b' => 'value', ] ]
все предлагаемые решения сведут его к минимуму
['value']
, но при этом теряется информация о ключе и глубине, плюс, если у вас есть другой ключ «b» где-то еще, он перезапишет их.Я хотел получить такой результат:
[ 'a_b' => 'value', ]
array_walk_recursive
не передает информацию о рекурсивном ключе, поэтому я сделал это простой рекурсией:function flatten($array, $prefix = '') { $return = []; foreach ($array as $key => $value) { if (is_array($value)) { $return = array_merge($return, flatten($value, $prefix . $key . '_')); } else { $return[$prefix . $key] = $value; } } return $return; }
Измените префикс $ и разделитель '_' по своему вкусу.
Площадка здесь: https://3v4l.org/0B8hf
источник
Вы можете использовать функцию flatten из нестандартной библиотеки PHP (NSPL) . Он работает с массивами и любыми повторяемыми структурами данных.
assert([1, 2, 3, 4, 5, 6, 7, 8, 9] === flatten([[1, [2, [3]]], [[[4, 5, 6]]], 7, 8, [9]]));
источник
Простой подход .. Смотрите через рекурсию ..
<?php function flatten_array($simple){ static $outputs=array(); foreach ( $simple as $value) { if(is_array($value)){ flatten_array($value); } else{ $outputs[]=$value; } } return $outputs; } $eg=['s'=>['p','n'=>['t']]]; $out=flatten_array($eg); print_r($out); ?>
источник
static
для этой задачи используется потенциально плохая идея? Непреднамеренное сохранение данных. Это наверняка застает программистов врасплох, если они не знают / не ожидают такого поведения. Посмотрите на эту демонстрацию .Кто-то может счесть это полезным, у меня возникла проблема со сглаживанием массива в каком-то измерении, я бы назвал его последним измерением, например, если у меня есть массив вроде:
array ( 'germany' => array ( 'cars' => array ( 'bmw' => array ( 0 => 'm4', 1 => 'x3', 2 => 'x8', ), ), ), 'france' => array ( 'cars' => array ( 'peugeot' => array ( 0 => '206', 1 => '3008', 2 => '5008', ), ), ), )
Или же:
array ( 'earth' => array ( 'germany' => array ( 'cars' => array ( 'bmw' => array ( 0 => 'm4', 1 => 'x3', 2 => 'x8', ), ), ), ), 'mars' => array ( 'france' => array ( 'cars' => array ( 'peugeot' => array ( 0 => '206', 1 => '3008', 2 => '5008', ), ), ), ), )
Для обоих этих массивов, когда я вызываю метод ниже, я получаю результат:
array ( 0 => array ( 0 => 'm4', 1 => 'x3', 2 => 'x8', ), 1 => array ( 0 => '206', 1 => '3008', 2 => '5008', ), )
Итак, я сглаживаю последнее измерение массива, которое должно остаться прежним, метод ниже можно отредактировать, чтобы фактически остановиться на любом уровне:
function flattenAggregatedArray($aggregatedArray) { $final = $lvls = []; $counter = 1; $lvls[$counter] = $aggregatedArray; $elem = current($aggregatedArray); while ($elem){ while(is_array($elem)){ $counter++; $lvls[$counter] = $elem; $elem = current($elem); } $final[] = $lvls[$counter]; $elem = next($lvls[--$counter]); while ( $elem == null){ if (isset($lvls[$counter-1])){ $elem = next($lvls[--$counter]); } else{ return $final; } } } }
источник
Если вас интересуют только значения одного конкретного ключа, вы можете найти этот подход полезным:
function valuelist($array, $array_column) { $return = array(); foreach($array AS $row){ $return[]=$row[$array_column]; }; return $return; };
Пример:
Учитывая $ get_role_action =
array(3) { [0]=> array(2) { ["ACTION_CD"]=> string(12) "ADD_DOCUMENT" ["ACTION_REASON"]=> NULL } [1]=> array(2) { ["ACTION_CD"]=> string(13) "LINK_DOCUMENT" ["ACTION_REASON"]=> NULL } [2]=> array(2) { ["ACTION_CD"]=> string(15) "UNLINK_DOCUMENT" ["ACTION_REASON"]=> NULL } }
чем
$variables['role_action_list']=valuelist($get_role_action, 'ACTION_CD');
приведет к:$variables["role_action_list"]=> array(3) { [0]=> string(12) "ADD_DOCUMENT" [1]=> string(13) "LINK_DOCUMENT" [2]=> string(15) "UNLINK_DOCUMENT" }
Оттуда вы можете выполнять поиск значений следующим образом:
if( in_array('ADD_DOCUMENT', $variables['role_action_list']) ){ //do something };
источник
ничего из этого не сработало для меня ... поэтому пришлось запустить его самому. работает нормально:
function arrayFlat($arr){ $out = ''; foreach($arr as $key => $value){ if(!is_array($value)){ $out .= $value.','; }else{ $out .= $key.','; $out .= arrayFlat($value); } } return trim($out,','); } $result = explode(',',arrayFlat($yourArray)); echo '<pre>'; print_r($result); echo '</pre>';
источник
Для данного многомерного массива и преобразования его в одномерный можно отключить все значения, которые имеют массивы, и сохранить их в первом измерении, например:
function _flatten_array($arr) { while ($arr) { list($key, $value) = each($arr); is_array($value) ? $arr = $value : $out[$key] = $value; unset($arr[$key]); } return (array)$out; }
источник
each()
устарел с php7.2.