2009-12-23 8 views
2

I ont une fonction qui doit accepter un tableau de points, ou un réseau de matrice de points (a 2 ou 3 matrice bidimensionnelle). Je suis à la recherche d'un moyen fiable de détecter si elle a 2 ou 3 niveaux. La chose est, je ne peux pas compter sur les clés des tableaux pour faire la vérification, cette coutume travail:Comment calculer correctement le nombre de niveaux dans un tableau?

$levels = isset($array[0][0]) && is_array($array[0][0]) ? 3 : 2; 

..as la première clé pourrait ne pas être 0. Il est généralement, mais je ne Je ne veux pas compter sur ça. Et de toute façon, c'est une façon minable et étroite de le faire. Idéalement, je voudrais vérifier un certain nombre de niveaux sans avoir à boucle à travers le réseau entier.

Voici ce que les tableaux pourraient ressembler:

array(5) { 
    [2] => array(2) { 
     [x] => 3 
     [y] => 6 
    } 
    [3] => array(2) { 
     [x] => 4 
     [y] => 8 
    } 
    ... 

Et un tableau à trois dimensions contiendrait ces tableaux.

Quelques notes:

  • Les tableaux sont grandes, si une boucle complètement à travers les tableaux ne sont pas une très bonne option
  • Les tableaux sont numériquement et séquentiellement indexés (à l'exception du dernier niveau, qui a x et y)
  • Les clés du tableau peuvent ou non partir de 0

Tout en écrivant cela, je suis venu avec une solution qui pourrait être réalisable; une fonction récursive qui vérifie le premier élément d'un tableau, si elle est, puis s'appeler sur le tableau nouvellement trouvé etc.

Existe-t-il des meilleures idées, plus propres? Les points de bonus pour supporter des tableaux qui pourraient avoir les deux valeurs scalaires et les tableaux (par ex. le premier élément d'un tableau peut être une chaîne, mais suivant est un tableau).

+0

Je ne pense pas qu'il y ait un autre moyen, car le tableau PHP est implémenté en tant qu'arbre et non en tant que tableau, donc il ne sait pas combien de "niveaux" il y a dans le tableau. –

Répondre

5

Si vous attendez une gamme complète ou une gamme complète de tableaux que vous pourriez essayer: -

if (isset $points[0][0][0]) 

Si toutefois votre tableau est plus difficile clairsemés son. Le problème de base est qu'un "tableau" php est en réalité un hachage unidimensionnel. L'astuce étant qu'une valeur peut être un autre "tableau". Vous devez donc accéder au deuxième niveau pour déterminer si c'est une valeur ou un tableau.

Encore une fois si vous vous attendez à un tableau donné pour contenir des valeurs de point seulement, ou seulement d'autres tableaux que vous ne devez vérifier une entrée si:

if (is_array(current(current($points)))) 

Si vous obtenez ce que vous voulez: le (courant ) La fonction renvoie le pointeur de tableau courant (par défaut le premier - donc il sera toujours défini sur quelque chose), donc le courant interne ($ points) vous donnerait $ points [0] ou la première entrée avec une valeur réelle, comme le le courant extérieur vous rapportera quelque chose comme $ points [0] [0].

+0

La solution actuelle (en cours ($ points)) fonctionne très bien dans ce cas, je vais donc l'utiliser. Au moins, c'est plus propre que tout ce que j'ai compris et ça fonctionne aussi sur des tableaux avec des clés de départ inconnues. Merci! –

1

Je ne vois pas comment vous pouvez le faire sans au moins itérer à travers le réseau. Le fait est que n'importe lequel des éléments de votre tableau pourrait avoir un niveau supplémentaire. En conséquence, chaque élément doit être testé.

Cela étant dit, vous pouvez toujours utiliser la récursivité pour améliorer votre code un peu:

/** 
* Determine the maximum depth of an array. 
* @param $input The object to test. Might be an array, or might be an int (or 
*  any other object). 
* @param $startDepth The starting depth. Will be added as an offset to the 
*  result. 
* @return The depth of the array, plus any initial offset specified in 
*   $startDepth. 
*/ 
function testDepth($input, $startDepth = 0) { 
    if (is_array($input) { 
     $max = $startDepth; 
     for ($array as $i) { 
      // Check what the depth of the given element is 
      $result = testDepth($i, $startDepth + 1); 
      // We only care about the maximum value 
      if ($result > $max) { 
       $max = $result; 
      } 
     } 
     return $max; 
    } else { 
     // This isn't an array, so it's assumed not to be a container. 
     // This doesn't add any depth to the parent array, so just return $startDepth 
     return $startDepth; 
    } 
} 

testDepth($array); 
+0

Il n'y a pas une telle construction en PHP comme: pour ($ array as $ i) { Avez-vous testé votre code? – mrarm

1

$ levels = is_array (current (current ($ array)))? 3: 2;

Questions connexes