2013-02-15 8 views
3

Disons que j'ai un tableau comme celui-ci:obtenir toutes les clés du tableau de valeur

Array 
(
[Start] => Array 
    (
     [Item 1] => Array 
      (
       [0] => Item 1_1 
       [Item 2_1] => Array 
        (
         [Item 2_1_1] => x 
        ) 

       [1] => Item 3_1 
      ) 

     [0] => Item 2 
     [1] => Item 3 
    ) 

)

Y at-il une fonction php que je peux utiliser pour obtenir le chemin qui mène à la valeur x dans mon tableau, ce qui signifie, dans ce cas le résultat serait:

Start, Item 1, Item 2_1, Item 2_1_1, x 
+0

Vous pouvez essayer avec 'serialize()' – fedorqui

+0

Découvrez des algorithmes de recherche graphique, comme BFS et DFS. –

+0

array_search()? –

Répondre

2

la seule méthode que je peux penser actuellement serait beaucoup de foreach ($array as $key => $value) boucles imbriquées avec array_search().

Il serait préférable d'en faire un modèle récursif, il serait donc judicieux d'utiliser une fonction.

function recursiveSearch($key, $array) 
{ 
    foreach ($array as $k => $ar) { 
     if (is_array('x', $ar)) { 
      return $k . ', ' . array_search('x', $ar); 
     } else { 
      if ($ar === 'x') { 
       return $k 
      } else { 
       return recursiveSearch($key, $ar); 
      } 
     } 
    } 
} 

Juste une prise sur elle, ne fonctionne pas nécessairement ou quelque chose comme ça.

+0

+1 bien STYLE DE CODAGE ET APPROCHE CORRECTE –

1

Le problème que vous rencontrez implique une récursion et/ou une traversée d'arbre. PHP supporte la traversée d'arbre d'un tableau avec les RecursiveArrayIterator et RecursiveIteratorIterator.

Pour obtenir toutes les clés de tous les tableaux parents, vous devez aller du premier niveau à la profondeur actuelle et récupérer les clés. Ceci est également supporté par RecursiveIteratorIterator avec la méthode getSubIterator(). Ce n'est pas vraiment bien documenté dans le manuel, alors voici un exemple:

$it = new RecursiveIteratorIterator(
    new RecursiveArrayIterator($array) 
); 

foreach ($it as $value) { 
    if ($value !== 'x') continue; 

    $keys = array(); 
    $depth = $it->getDepth(); 
    for ($i = 0; $keys[] = $it->getSubIterator($i)->key(), $depth--; $i++); 

    echo implode(', ', $keys), ', ', $value, "\n"; 
} 

Dans cet exemple, tout d'abord la RecursiveArrayIterator avec votre $array est créé. Pour activer la traversée de l'arbre, il est enveloppé dans le RecursiveIteratorIterator. Ceci est nécessaire pour utiliser l'$it -iterator avec le foreach d'une manière récursive.

À l'intérieur du foreach, la valeur du tableau est ensuite comparée à votre valeur de recherche. S'il ne correspond pas, il continue avec la valeur suivante. Mais s'il correspond aux méthodes getDepth() et getSubIterator() sur l'itérateur récursif, elles sont utilisées pour créer la matrice de clés.

L'exemple ne la sortie suivante:

Start, Item 1, Item 2_1, Item 2_1_1, x 

Ce qui correspond à votre description dans la question. Parce que ce sont des itérateurs, vous pouvez également implémenter cela dans une classe qui lui est propre. Ce qui suit classe Iterator permet non seulement de faire l'arbre-traversal sur le tableau fourni dans le constructeur, mais a aussi une méthode nommée getKeys() qui retourne un tableau contenant toutes les clés du niveau le plus bas à la profondeur actuelle:

/** 
* Class ArrayRecursiveKeysIterator 
*/ 
class ArrayRecursiveKeysIterator extends RecursiveIteratorIterator 
{ 
    /** 
    * @param array $array 
    */ 
    public function __construct(array $array) 
    { 
     parent::__construct(new RecursiveArrayIterator($array)); 
    } 

    /** 
    * @return array keys 
    */ 
    public function getKeys() 
    { 
     for ($k = [], $i = 0, $m = $this->getDepth(); $i <= $m; $i++) 
      $k[] = $this->getSubIterator($i)->key(); 
     return $k; 
    } 
} 

Il est alors plus facile à utiliser (et probablement aussi pour d'autres scénarios). Donc, d'abord un exemple d'utilisation de base. Parcourez le tableau pour afficher toutes les clés de chaque valeur.Instancier le iterator pour votre tableau et la sortie des clés par chaque valeur:

$it = new ArrayRecursiveKeysIterator($array); 
foreach ($it as $value) { 
    echo implode(', ', $it->getKeys()), ', ', $value, "\n"; 
} 

Cela crée la sortie suivante:

Start, Item 1, 0, Item 1_1 
Start, Item 1, Item 2_1, Item 2_1_1, x 
Start, Item 1, 1, Item 3_1 
Start, 0, Item 2 
Start, 1, Item 3 

Dans votre scénario, vous voulez aussi de filtrer l'itérateur base d'une valeur spécifique (ici la chaîne "x") que vous pouvez facilement faire en utilisant le RegexIterator qui est un FilterIterator. Voilà donc votre scénario:

$it  = new ArrayRecursiveKeysIterator($array); 
$filter = new RegexIterator($it, '~^x$~'); 
foreach ($filter as $value) { 
    echo implode(', ', $it->getKeys()), ', ', $value, "\n"; 
} 

Et ici la sortie.

Start, Item 1, Item 2_1, Item 2_1_1, x 

Comme vous pouvez le voir, il est filtré pour la valeur que vous êtes intéressé par

D'autres questions connexes vous « re probablement intéressé sont:

+0

+ bonne explication ... pourquoi ne pas simplement aplatir le tableau – Baba

+0

Thx. Que veux-tu aplatir? Par l'itération c'est déjà dans l'ordre linéaire et les clefs sont seulement nécessaires pour une valeur spécifique, donc pas besoin d'aplatir le tableau entier je dirais. – hakre

+0

Vous avez raison .. ce qu'il veut, c'est une recherche récursive ... – Baba

Questions connexes