tiempo studio recorrer mismo matrices array php arrays recursion multidimensional-array

php - recorrer - matrices en r studio



PHP convierte una matriz anidada a una sola matriz mientras concatena las teclas? (5)

Aquí hay una matriz de ejemplo:

$foo = array( ''employer'' => array( ''name'' => ''Foobar Inc'', ''phone'' => ''555-555-5555'' ), ''employee'' => array( ''name'' => ''John Doe'', ''phone'' => ''555-555-5556'', ''address'' => array( ''state'' => ''California'', ''zip'' => ''90210'' ) ), ''modified'' => ''2009-12-01'', );

Y me gustaría obtener un resultado como este:

$fooCompressed = array( ''employer_name'' => ''Foobar Inc'', ''employer_phone'' => ''555-555-5555'', ''employee_name'' => ''John Doe'', ''employee_phone'' => ''555-555-5556'' ''employee_address_state'' => ''California'', ''employee_address_zip'' => ''90210'', ''modified'' => ''2009-12-01'' )

¿Cómo podría escribir una función recursiva para manejar esto?


Algo como esto:

function makeNonNestedRecursive(array &$out, $key, array $in){ foreach($in as $k=>$v){ if(is_array($v)){ makeNonNestedRecursive($out, $key . $k . ''_'', $v); }else{ $out[$key . $k] = $v; } } } function makeNonNested(array $in){ $out = array(); makeNonNestedRecursive($out, '''', $in); return $out; } // Example $fooCompressed = makeNonNested($foo);


Aquí hay una función que le permite especificar un prefijo de nivel superior a través del segundo parámetro:

function flatten_array($array, $prefix = null) { if ($prefix) $prefix .= ''_''; $items = array(); foreach ($array as $key => $value) { if (is_array($value)) $items = array_merge($items, flatten_array($value, $prefix . $key)); else $items[$prefix . $key] = $value; } return $items; }


/** * Flatten a multi-dimensional array or a nested object, constructing concatenated keys for * nested elements. * @param array or object $array - the array or object to be flattened * @param array or string $key_path - current parent keys path. * Pass this parameter as string if you need to set a common prefix for all keys * @param string $level_separator - keys concatenation glue * @param array $flat - resulting flattened array (omit this parameter when calling the function) * @return single-dimensional array with all array keys as concatenated keys of elements'' * paths through the data structure */ function flattenArray($array, &$key_path = array(), $level_separator = ''.'', &$flat = array()) { if(!is_array($key_path)) { // sanitize key_path $key_path = array((string)$key_path); } foreach($array as $key => $value) { // push current key to path array_push($key_path, $key); if(is_array($value) || is_object($value)) { // next level recursion $flat = array_merge($flat, flattenArray($value, $key_path, $level_separator, $flat)); } else { // write the value directly $flat[implode($level_separator, $key_path)] = $value; } // remove used key array_pop($key_path); } return $flat; }


Después de algunas iteraciones, he podido refinar una solución a este problema que utiliza un enfoque basado en la pila para evitar la recursión, simplificando un poco las cosas.

/*** * @name array_flatten * @author Tom Penzer @tpenzer * Flattens a multi-tiered array into a single-tiered * associative array with keys reflective of their * values'' hierarchy. * * @param array $array Required - the multi- * level keyed array to be flattened * @param string $separator Optional - the string * used to separate the keys from different levels of * the hierarchy * * @return array a single-level keyed array ***/ function array_flatten($array, $separator = ''_'') { $output = array(); while (list($key, $value) = each($array)) { if (is_array($value)) { $build = array(); foreach ($value as $s_key => $s_value) { $build[$key . $separator . $s_key] = $s_value; } unset($array[$key]); $array = $build + $array; unset($build); continue;//skip write to $output } $output[$key] = $value; unset($array[$key]); } return $output; }

No es exactamente el método solicitado, pero es un buen contraste con los enfoques recursivos del problema.


Creo que este ''truco'' de uso es http_build_query, es menos desagradable que recurrencia (o al menos dejar que php lo haga por usted)

3 líneas de código si su str_replace usa los valores codificados en url para [y]

$string = http_build_query($array); $string = urldecode($string); $string = str_replace( array(''['','']''), array(''_'','''') , $string ); parse_str($string, $flat_array);

$ flat_array se convierte en:

array(7) { ["employer_name"] =>"Foobar Inc" ["employer_phone"] =>"555-555-5555" ["employee_name"] =>"John Doe" ["employee_phone"] =>"555-555-5556" ["employee_address_state"]=>"California" ["employee_address_zip"] =>"90210" ["modified"] =>"2009-12-01" }