Estoy tratando de acceder a una matriz anidada (una matriz que contiene matrices que contiene matrices...)
Necesito obtener el último valor, dada la matriz y la ruta de las claves.
Dado foo y a... zi necesitan obtener
foo[a][b][c]…[x][y][z]Me pregunto si hay alguna forma más elegante que esta.
function getValueRecursive(array $array, string ...$identifyer){ $value = $array; foreach($identifyer as $key){ if(!key_exists($key, $value)) return NULL; $value = $value[$key]; } return $value; } $foo = [ 'a' => [ 'b' => [ 'c' => "Hallo Welt!" ] ] ]; echo getValueRecursive($foo, 'a', 'b', 'c'); // Returns "Hallo Welt!" <?php $foo = [ 'a' => [ 'b' => [ 'c' => "Hallo Welt!" ] ] ]; $result=array(); array_walk_recursive($foo, function($value,$key) use (&$result){ $result[]=$value; }); print_r($result[0]);O
<?php ini_set("display_errors", 1); $foo = [ 'a' => [ 'b' => [ 'c' => "Hallo Welt!" ] ] ]; echo getValueOfArray($foo,"a","b","c"); function getValueOfArray($array) { $args=func_get_args(); unset($args[0]); $string=""; foreach($args as $value) { $string.="['$value']"; } eval('if(isset($array'.$string.')) { $result= $array'.$string.'; }'); return $result; } Salida: Hallo Welt!
Hace algún tiempo escribí una biblioteca de matrices que usa la interfaz ArrayAccess para lograr tales operaciones. Permite no solo recuperar sino también almacenar y eliminar valores.
Para todos los métodos offset*() utilicé el método de orden superior walkThroughOffsets :
protected function walkThroughOffsets( &$array, Callable $baseCaseAction, Callable $offsetNotExistsAction ) { $offset = array_shift($this->offsets); if (is_scalar($offset) && isset($array[$offset])) { if (empty($this->offsets)) { return $baseCaseAction($array, $offset); } return $this->walkThroughOffsets( $array[$offset], $baseCaseAction, $offsetNotExistsAction ); } return $offsetNotExistsAction($array, $offset); } Con este método, puede implementar el método offsetGet (que se llama cuando intenta acceder al valor de la matriz) de esta manera:
public function offsetGet($offset) { $this->setOffsets($offset); return $this->walkThroughOffsets( $this->container, function ($array, $offset) { return $array[$offset]; }, $this->undefinedOffsetAction ); }Entonces puede obtener valores tan simples como con la matriz habitual:
$array = new CompositeKeyArray([ 'foo' => [ 'bar' => 'baz' ] ]); var_dump($array[['foo', 'bar']]); // => string(3) "baz" var_dump($array[['foo', 'quux']]); // => PHP Fatal error: Uncaught UndefinedOffsetException: Undefined offset quux.Su enfoque es muy similar a lo que yo recomendaría. Supongo que esto es básicamente una técnica de "apilamiento" en lugar de hacer llamadas condicionales/repetitivas de la función personalizada. Considero que su enfoque es lo suficientemente elegante.
Ajustes:
null ), por lo que no es apropiado return null arbitrariamente cuando se proporciona una ruta de clave no válida. En su lugar, lance una excepción para que se pueda hacer una diferenciación de los resultados donde sea que se llame a la función.Código: ( Demo ) ( Fringe Case )
function getValueRecursive(array $array, ...$keys) { foreach ($keys as $key) { if (!key_exists($key, $array)) { throw new Exception('key path invalid'); } $array = $array[$key]; } return $array; } $foo = [ 'a' => [ 'b' => [ 'c' => "Hallo Welt!" ] ] ]; try { var_export(getValueRecursive($foo, 'a', 'b', 'c')); echo "\n---\n"; var_export(getValueRecursive($foo, 'a', 'b')); echo "\n---\n"; var_export(getValueRecursive($foo, 0, 'b', 'c')); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); }Producción:
'Hallo Welt!' --- array ( 'c' => 'Hallo Welt!', ) --- Caught exception: key path invalid