2009-11-04 10 views
8

Digamos que tengo una matriz como:¿Cómo usar una cadena como una ruta de índice de matriz para recuperar un valor?

Array 
(
    [0] => Array 
     (
      [Data] => Array 
       (
        [id] => 1 
        [title] => Manager 
        [name] => John Smith 
       ) 
     ) 
    [1] => Array 
     (
      [Data] => Array 
       (
        [id] => 1 
        [title] => Clerk 
        [name] => 
         (
          [first] => Jane 
          [last] => Smith 
         ) 
       ) 

     ) 

) 

Quiero ser capaz de construir una función que pueda pasar una cadena a que actuará como la ruta de índice de matriz y devuelve el valor de la matriz adecuada sin usar eval() . ¿Es eso posible?

function($indexPath, $arrayToAccess) 
{ 
    // $indexPath would be something like [0]['Data']['name'] which would return 
    // "Manager" or it could be [1]['Data']['name']['first'] which would return 
    // "Jane" but the amount of array indexes that will be in the index path can 
    // change, so there might be 3 like the first example, or 4 like the second. 

    return $arrayToAccess[$indexPath] // <- obviously won't work 
} 

Respuesta

9

puede utilizar una matriz como camino (de izquierda a derecha), entonces una función recursiva:

$indexes = {0, 'Data', 'name'}; 

function get_value($indexes, $arrayToAccess) 
{ 
    if(count($indexes) > 1) 
    return get_value(array_slice($indexes, 1), $arrayToAccess[$indexes[0]]); 
    else 
    return $arrayToAccess[$indexes[0]]; 
} 
+0

Agradable. Nota para copiar y pegar: la llamada recursiva a 'getValue' no coincide del todo con el nombre de la función 'get_value'. Deben coincidir para funcionar correctamente. – grossvogel

+0

esto ahora está arreglado – Ash

+0

¡Este es un gran ejemplo! Gracias @manji! – Michael

0

Tiene que analizar indexPath string. Elija un separador (por ejemplo, "."), Lea el texto hasta "." esa sería la primera clave, luego leer el resto hasta el próximo, esa sería la siguiente clave. Haz eso hasta que no haya más puntos.

Puede almacenar la clave en la matriz. Haga un bucle foreach en esta matriz para obtener el elemento buscado.

-1

Si ya conoce el elemento de matriz exacto que está extrayendo, ¿por qué escribir una función para hacerlo? Lo que está mal con sólo

$array[0]['data']['title'] 
+0

Estoy frente a la misma cuestión. Tengo una matriz compleja. Necesito encontrar una determinada clave, obtener su dirección, luego obtener datos adicionales e insertarla en esa clave. Así que, básicamente, necesito almacenar una dirección de inxes y ellos abordan un artículo. –

0

Aquí es una manera de hacer el trabajo, si la cadena de análisis es la forma en que quieres ir.

$data[0]["Data"]["stuff"] = "cake"; 

$path = "[0][\"Data\"]['stuff']"; 

function indexPath($path,$array){ 
    preg_match_all("/\[['\"]*([a-z0-9_-]+)['\"]*\]/i",$path,$matches); 

    if(count($matches[1]) > 0) { 
     foreach ($matches[1] as $key) { 
       if (isset($array[$key])) { 
         $array = $array[$key]; 
       } else { 
         return false; 
       } 
     } 
    } else { 
     return false; 
    } 

return $array; 
} 

print_r(indexPath($path,$data)); 
0

Un preg_match_all, ciclismo a través de los resultados emparejados le daría cerca de los resultado que quería. Debe tener cuidado con todas las estrategias enumeradas aquí para obtener información perdida. Por ejemplo, debe idear una forma de asegurarse de que 55 se mantenga como tipo int y no se analice como tipo cadena.

16

Un poco más tarde, pero ... esperanza ayuda a alguien:

// $pathStr = "an:string:with:many:keys:as:path"; 
$paths = explode(":", $pathStr); 
$itens = $myArray; 
foreach($paths as $ndx){ 
    $itens = $itens[$ndx]; 
} 

Ahora Ítenes es la parte de la matriz que quería.

[ 's]

laboratorios

+1

¡Verdaderamente brillante! Gracias hombre :) – CoR

2

Ésta es una cuestión de edad, sino que se ha hecho referencia como esta pregunta surge con frecuencia.

Hay algunas funciones recursivas pero yo uso una referencia:

function array_nested_value($array, $path) { 
    $temp = &$array; 

    foreach($path as $key) { 
     $temp =& $temp[$key]; 
    } 
    return $temp; 
} 

$path = array(0, 'Data', 'Name'); 
$value = array_nested_value($array, $path); 
2

Intente lo siguiente, donde $ indexPath se formatea como una ruta de archivo es decir,

'<array_key1>/<array_key2>/<array_key3>/...'. 

function($indexPath, $arrayToAccess) 
{ 
    $explodedPath = explode('/', $indexPath); 
    $value =& $arrayToAccess; 
    foreach ($explodedPath as $key) { 
     $value =& $value[$key]; 
    } 
    return $value; 
} 

por ejemplo, usando los datos de la pregunta, $ indexPath = '1/Data/name/first' devolvería $ value = Jane.

0

Además de abracadaver:

function array_nested_value($array, $path) { 

    foreach($path as $key) { 

     $array = $array[$key]; 
    } 

    return $array; 
} 

$path = array(0, 'Data', 'Name'); 
$value = array_nested_value($array, $path); 

Posible uso

function get_array_value($array=array(), $path=array()){ 

    foreach($path as $key) { 

     if(isset($array[$key])){ 

      $array=$array[$key]; 
     } 
     else{ 

      $array=NULL; 
      break; 
     } 
    } 

    return $array; 
} 

function custom_isset($array=array(), $path=array()){ 

    $isset=true; 

    if(is_array($array)&&is_null(get_array_value($array, $path))){ 

     $isset=false; 
    } 

    return $isset; 
} 

function is($array=array(), $path=array()){ 

    $is=false; 

    if(is_array($array)){ 

     $array_value=get_array_value($array, $path); 

     if(is_bool($array_value)){ 

      $is=$array_value; 
     } 
    } 

    return $is; 
} 

Ejemplo

$status=[]; 

    $status['updated']=true; 

     if(is($status,array('updated'))){ 

       //do something... 

     } 

Recursos

https://gist.github.com/rafasashi/0d3ebadf08b8c2976a9d

1
function($indexPath, $arrayToAccess) 
{ 
    eval('$return=$arrayToAccess'.$indexPath.';'); 
    return $return; 
} 
Cuestiones relacionadas