Prawdopodobnie jest to pytanie dla początkujących, ale już przeglądam dokumentację i nie mogę znaleźć żadnego rozwiązania. Pomyślałem, że mógłbym użyć implode dla każdego wymiaru, a następnie złożyć te ciągi z powrotem razem, str_split
aby utworzyć nową prostą tablicę. Jednak nigdy nie wiem, czy wzorzec łączenia nie jest również w wartościach, więc po wykonaniu str_split
moich oryginalnych wartości mogą się zepsuć.
Czy jest coś podobnego combine($array1, $array2)
do tablic wewnątrz wielowymiarowej tablicy?
php
arrays
multidimensional-array
Adrianna
źródło
źródło
Odpowiedzi:
Posługiwać się
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) } */ ?>
Testowane z PHP 5.5.9-1ubuntu4.24 (cli) (zbudowano: 16 marca 2018 12:32:06)
źródło
$objTmp
w tym przykładzie) są przekazywane automatycznie przez odwołanie; tablice nie są. Spróbuj użyć funkcji anonimowej ( php.net/manual/en/functions.anonymous.php ) zamiastcreate_function
.This bug has been fixed in SVN.
array_values()
? W ogóle nie widzę zastosowania tej funkcji w odpowiedzi.$array = your array $result = call_user_func_array('array_merge', $array); echo "<pre>"; print_r($result);
REF: http://php.net/manual/en/function.call-user-func-array.php
Oto inne rozwiązanie (działa z tablicą wielowymiarową):
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);
źródło
$result = array_merge(...$array);
php.net/manual/en/ ...To jest jedna linia, BARDZO łatwa w użyciu:
$result = array(); array_walk_recursive($original_array,function($v) use (&$result){ $result[] = $v; });
Jest to bardzo łatwe do zrozumienia wewnątrz anonimowej funkcji / zamknięcia.
$v
to wartość twojego$original_array
.źródło
// $array = your multidimensional array $flat_array = array(); foreach(new RecursiveIteratorIterator(new RecursiveArrayIterator($array)) as $k=>$v){ $flat_array[$k] = $v; }
Udokumentowane również: http://www.phpro.org/examples/Flatten-Array.html
źródło
iterator_to_array()
do tej odpowiedzi zanegowałoby potrzebęforeach
pętli. Mogłaby to być prosta funkcja jednowierszowa. (aczkolwiek dość długa, jednoliniowa)Jeśli masz tablicę tablic, która nie przekracza jednego poziomu (przypadek użycia, który uważam za powszechny), możesz uciec od
array_merge
operatora i splat.<?php $notFlat = [[1,2],[3,4]]; $flat = array_merge(...$notFlat); var_dump($flat);
Wynik:
array(4) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> int(4) }
Operator splat skutecznie zmienia tablicę tablic na listę tablic jako argumenty dla
array_merge
.źródło
$flat = array_merge( array_keys( $notFlat ), ...array_values( $notFlat ) );
W PHP 7 możesz użyć generatorów i delegowania generatorów (
yield from
) do spłaszczenia tablicy: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); }
Przykład:
$array = [ 1, 2, [ 3, 4, 5, [ 6, 7 ], 8, 9, ], 10, 11, ]; var_dump(array_flatten($array));
http://3v4l.org/RU30W
źródło
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; }
źródło
Inna metoda z komentarzy użytkowników PHP (uproszczona) i tutaj :
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; }
Dużą zaletą tej metody jest to, że śledzi ona głębokość rekursji, jeśli zajdzie taka potrzeba podczas spłaszczania.
Spowoduje to wyświetlenie:
$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 )
źródło
Rozwiązanie nierekurencyjne (ale niszczące porządek):
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; }
źródło
W PHP> = 5.3 i na podstawie odpowiedzi Luca M. (pierwszej) możesz użyć takich zamknięć
array_walk_recursive($aNonFlat, function(&$v, $k, &$t){$t->aFlat[] = $v;}, $objTmp);
Uwielbiam to, ponieważ nie muszę otaczać kodu funkcji cudzysłowami, jak w przypadku funkcji create_function ()
źródło
objTemp
rzeczyKorzystanie z funkcji wyższego rzędu (uwaga: używam wbudowanych funkcji anonimowych , które pojawiły się w 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() ); }
źródło
Nowe podejście oparte na poprzedniej przykładowej funkcji przesłanej przez chaos, która naprawia błąd nadpisywania kluczy ciągów w multiarrays:
# 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);
źródło
/*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; }
źródło
możesz spróbować tego:
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; }
źródło
Jeśli nie przeszkadza ci utrata kluczy tablicowych, możesz spłaszczyć tablicę wielowymiarową, używając zamknięcia rekurencyjnego jako wywołania zwrotnego, które wykorzystuje wartość array_values (), upewniając się, że to wywołanie zwrotne jest parametrem dla array_walk (), jak poniżej.
<?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);
Jedyną wadą poprzedniego przykładu jest to, że obejmuje on napisanie znacznie większej ilości kodu niż poniższe rozwiązanie, które używa funkcji array_walk_recursive () wraz z uproszczonym wywołaniem zwrotnym:
<?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);
Zobacz kod na żywo
Ten przykład wydaje się lepszy od poprzedniego, ukrywając szczegóły dotyczące wyodrębniania wartości z wielowymiarowej tablicy. Z pewnością dochodzi do iteracji, ale bez względu na to, czy pociąga za sobą rekursję, czy struktury kontrolne, będziesz wiedzieć tylko z tablicy array.c . Ponieważ programowanie funkcjonalne koncentruje się na danych wejściowych i wyjściowych, a nie na drobiazgach związanych z uzyskaniem wyniku, z pewnością można nie przejmować się tym, w jaki sposób zachodzi iteracja za kulisami, to znaczy do czasu, gdy pracodawca z perspektywy zadaje takie pytanie.
źródło
Znalazłem prosty sposób na przekształcenie tablicy wielopoziomowej w jedną. Używam funkcji „http_build_query”, która konwertuje tablicę na ciąg adresu URL. Następnie podziel ciąg za pomocą polecenia Rozbij i zdekoduj wartość.
Oto próbka.
$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;
źródło
Przepraszam za nekroboping, ale żadna z udzielonych odpowiedzi nie dała tego, co intuicyjnie rozumiałem jako „spłaszczanie wielowymiarowej tablicy”. Mianowicie ten przypadek:
[ 'a' => [ 'b' => 'value', ] ]
wszystkie dostarczone rozwiązania spłaszczyłyby go do postaci sprawiedliwej
['value']
, ale to powoduje utratę informacji o kluczu i głębokości, a jeśli masz inny klucz „b” gdzieś indziej, nadpisze je.Chciałem uzyskać taki wynik:
[ 'a_b' => 'value', ]
array_walk_recursive
nie przekazuje informacji o kluczu, który jest obecnie rekurenowany, więc zrobiłem to z prostą rekursją: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; }
Zmodyfikuj przedrostek $ i separator „_” według własnych upodobań.
Plac zabaw tutaj: https://3v4l.org/0B8hf
źródło
Możesz użyć funkcji flatten z niestandardowej biblioteki PHP (NSPL) . Działa z tablicami i dowolnymi iterowalnymi strukturami danych.
assert([1, 2, 3, 4, 5, 6, 7, 8, 9] === flatten([[1, [2, [3]]], [[[4, 5, 6]]], 7, 8, [9]]));
źródło
Proste podejście… Zobacz to poprzez rekursję…
<?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); ?>
źródło
static
się potencjalnie złego pomysłu do tego zadania? Niezamierzone przechowywanie danych. Z pewnością zaskoczy to programistów, jeśli nie znają / nie oczekują takiego zachowania. Spójrz na tę demonstrację .Ktoś może uznać to za przydatne, miałem problem ze spłaszczeniem tablicy w jakimś wymiarze, nazwałbym to ostatnim wymiarem więc na przykład jak mam tablicę jak:
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', ), ), ), )
Lub:
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', ), ), ), ), )
Dla obu tych tablic, gdy wywołuję poniższą metodę, otrzymuję wynik:
array ( 0 => array ( 0 => 'm4', 1 => 'x3', 2 => 'x8', ), 1 => array ( 0 => '206', 1 => '3008', 2 => '5008', ), )
Więc spłaszczam do ostatniego wymiaru tablicy, który powinien pozostać taki sam, poniższa metoda może zostać refaktoryzowana, aby faktycznie zatrzymać się na dowolnym poziomie:
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; } } } }
źródło
Jeśli interesują Cię tylko wartości jednego konkretnego klucza, może Ci się przydać to podejście:
function valuelist($array, $array_column) { $return = array(); foreach($array AS $row){ $return[]=$row[$array_column]; }; return $return; };
Przykład:
Biorąc pod uwagę $ 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 } }
niż
$variables['role_action_list']=valuelist($get_role_action, 'ACTION_CD');
spowodowałaby:$variables["role_action_list"]=> array(3) { [0]=> string(12) "ADD_DOCUMENT" [1]=> string(13) "LINK_DOCUMENT" [2]=> string(15) "UNLINK_DOCUMENT" }
Stamtąd możesz wyszukiwać wartości w następujący sposób:
if( in_array('ADD_DOCUMENT', $variables['role_action_list']) ){ //do something };
źródło
nic z tego nie działało dla mnie ... więc musiałem to uruchomić samodzielnie. działa dobrze:
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>';
źródło
Biorąc pod uwagę wielowymiarową tablicę i konwertując ją na jednowymiarową, można to zrobić usuwając wszystkie wartości, które mają tablice i zapisując je w pierwszym wymiarze, na przykład:
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; }
źródło
each()
jest przestarzały z php7.2.