864 votes

Comment vérifier si le tableau PHP est associatif ou séquentielle?

PHP traite tous les tableaux associatifs, donc il n'y a pas toutes les fonctions intégrées. Quelqu'un peut-il recommander une assez efficace pour savoir si un tableau contient uniquement les touches numériques?

En gros, je veux pouvoir faire la différence entre ce:

$sequentialArray = array('apple', 'orange', 'tomato', 'carrot');

et ceci:

$assocArray = array('fruit1' => 'apple', 
                    'fruit2' => 'orange', 
                    'veg1' => 'tomato', 
                    'veg2' => 'carrot');

709voto

Greg Points 132247

Vous avez posé deux questions qui ne sont pas tout à fait équivalent:

  • Tout d'abord, la façon de déterminer si un tableau a seulement les touches numériques de la
  • Deuxièmement, la façon de déterminer si un tableau a séquentiel touches numériques, à partir de 0

Considérer ces comportements vous avez réellement besoin. (Il se peut que ce soit le fera pour vous.)

La première question (il suffit de vérifier que toutes les clés sont numériques) est répondu par le Capitaine kurO.

Pour la deuxième question (vérifier si le tableau est zéro indexés et séquentielle), vous pouvez utiliser la fonction suivante:

<?php

function isAssoc($arr)
{
    return array_keys($arr) !== range(0, count($arr) - 1);
}

var_dump(isAssoc(array('a', 'b', 'c'))); // false
var_dump(isAssoc(array("0" => 'a', "1" => 'b', "2" => 'c'))); // false
var_dump(isAssoc(array("1" => 'a', "0" => 'b', "2" => 'c'))); // true
var_dump(isAssoc(array("a" => 'a', "b" => 'b', "c" => 'c'))); // true

?>

464voto

Captain kurO Points 659

Je suis tombé sur ce problème récemment, et ce est la façon dont j'ai vérifié si un tableau est associative ou pas:

function is_assoc($array) {
  return (bool)count(array_filter(array_keys($array), 'is_string'));
}

Cette fonction suppose:

  1. is_array($array) == true
  2. Si il y a au moins une chaîne de clé, $array sera considérée comme un tableau associatif

Espérons que cela aide.

145voto

Dave Marshall Points 1771

C'est sûrement une meilleure alternative.

<?php
$arr = array(1,2,3,4);
$isIndexed = array_values($arr) === $arr;

78voto

squirrel Points 1242

De nombreux intervenants dans cette question ne comprends pas comment les tableaux en PHP. À partir de la matrice de la documentation:

Une clé peut être un entier ou une chaîne de caractères. Si une clé est la représentation standard d'un nombre entier, il sera interprété en tant que tel (c'est à dire "8" sera interprété comme 8, tandis que la "08" sera interprété comme "08"). Flotte dans les principaux sont tronqués à l'entier. Les index et tableau associatif types sont du même type en PHP, qui peut à la fois contenir entier et une chaîne d'indices.

En d'autres termes, il n'y a pas une telle chose comme une clé du tableau de "8" car il sera toujours (silencieusement) converti à l'entier 8. Afin d'essayer de différencier les nombres entiers et les chaînes numériques est inutile.

Si vous voulez le moyen le plus efficace pour vérifier un tableau pour les non-entier touches sans faire une copie de la partie du tableau (comme array_keys ()) ou en totalité (comme foreach n'):

for (reset($my_array); is_int(key($my_array)); next($my_array));
$onlyIntKeys = is_null(key($my_array));

Cela fonctionne parce que la clé() retourne NULL si l'actuelle position de tableau est invalide et NUL ne peut jamais être une clé valide (si vous essayez d'utiliser la valeur NULL comme un tableau de clé, il obtient en silence convertis "").

41voto

Pang Points 2345

Comme indiqué par l'OP:

PHP traite tous les tableaux associatifs

il n'est pas tout à fait raisonnable (à mon humble avis) écrire une fonction qui vérifie si un tableau associatif. Donc, la première chose d'abord: qu'est ce qu'une clé dans un tableau PHP?:

La clé peut être un entier ou une chaîne de caractères.

Qui signifie qu'il y a 3 cas possibles:

  • Cas 1. toutes les touches sont numériques / les entiers.
  • Cas 2. toutes les clés sont des chaînes.
  • Cas 3. certaines clés sont des chaînes de caractères, certaines touches sont numériques / les entiers.

Nous pouvons vérifier chaque cas, avec les fonctions suivantes.

Cas 1: toutes les touches sont numériques / les entiers.

Remarque: Cette fonction renvoie vrai pour les tableaux vides.

//! Check whether the input is an array whose keys are all integers.
/*!
    \param[in] $InputArray          (array) Input array.
    \return                         (bool) \b true iff the input is an array whose keys are all integers.
*/
function IsArrayAllKeyInt($InputArray)
{
    if(!is_array($InputArray))
    {
        return false;
    }

    if(count($InputArray) <= 0)
    {
        return true;
    }

    return array_unique(array_map("is_int", array_keys($InputArray))) === array(true);
}

Cas 2: toutes les clés sont des chaînes de caractères.

Remarque: Cette fonction renvoie vrai pour les tableaux vides.

//! Check whether the input is an array whose keys are all strings.
/*!
    \param[in] $InputArray          (array) Input array.
    \return                         (bool) \b true iff the input is an array whose keys are all strings.
*/
function IsArrayAllKeyString($InputArray)
{
    if(!is_array($InputArray))
    {
        return false;
    }

    if(count($InputArray) <= 0)
    {
        return true;
    }

    return array_unique(array_map("is_string", array_keys($InputArray))) === array(true);
}

Cas 3. certaines clés sont des chaînes de caractères, certaines touches sont numériques / les entiers.

Remarque: Cette fonction renvoie vrai pour les tableaux vides.

//! Check whether the input is an array with at least one key being an integer and at least one key being a string.
/*!
    \param[in] $InputArray          (array) Input array.
    \return                         (bool) \b true iff the input is an array with at least one key being an integer and at least one key being a string.
*/
function IsArraySomeKeyIntAndSomeKeyString($InputArray)
{
    if(!is_array($InputArray))
    {
        return false;
    }

    if(count($InputArray) <= 0)
    {
        return true;
    }

    return count(array_unique(array_map("is_string", array_keys($InputArray)))) >= 2;
}

Il s'ensuit que:


Maintenant, pour un tableau à une "véritable" matrice que nous sommes tous habitués à, sens:

  • Ses touches sont toutes numériques / les entiers.
  • Ses touches sont séquentielle (c'est à dire par l'augmentation de l'étape 1).
  • Ses touches de commencer à partir de zéro.

Nous pouvons le vérifier avec la fonction suivante.

Cas 3a. les touches sont numérique / entiers, séquentielle, et de base zéro.

Remarque: Cette fonction renvoie vrai pour les tableaux vides.

//! Check whether the input is an array whose keys are numeric, sequential, and zero-based.
/*!
    \param[in] $InputArray          (array) Input array.
    \return                         (bool) \b true iff the input is an array whose keys are numeric, sequential, and zero-based.
*/
function IsArrayKeyNumericSequentialZeroBased($InputArray)
{
    if(!is_array($InputArray))
    {
        return false;
    }

    if(count($InputArray) <= 0)
    {
        return true;
    }

    return array_keys($InputArray) === range(0, count($InputArray) - 1);
}

Mises en garde / Pièges (ou, encore plus propre des faits à propos de la matrice de touches en PHP)

Entier clés

Les clés de ces tableaux sont des entiers:

array(0 => "b");
array(13 => "b");
array(-13 => "b");          // Negative integers are also integers.
array(0x1A => "b");         // Hexadecimal notation.

Clés de chaîne

Les clés de ces tableaux sont des chaînes de caractères:

array("fish and chips" => "b");
array("" => "b");                                   // An empty string is also a string.
array("stackoverflow_email@example.com" => "b");    // Strings may contain non-alphanumeric characters.
array("stack\t\"over\"\r\nflow's cool" => "b");     // Strings may contain special characters.
array('$tα€k↔øv∈rflöw⛄' => "b");                    // Strings may contain all kinds of symbols.
array("functіon" => "b");                           // You think this look fine? Think again! (see http://stackoverflow.com/q/9246051/1402846)
array("ま말轉转ДŁ" => "b");                         // How about Japanese/Korean/Chinese/Russian/Polish?
array("fi\x0sh" => "b");                            // Strings may contain null characters.
array(file_get_contents("https://www.google.com.hk/images/nav_logo114.png") => "b");    // Strings may even be binary!

Entier clés qui ressemblent à des cordes

Si vous pensez que la clé en array("13" => "b") est une chaîne de caractères, vous avez tort. À partir de la doc ici:

Les chaînes contenant un entier valide sera lancé pour le type integer. E. g. la touche "8" seront effectivement stockées sous 8. Sur l'autre main "08" ne soient pas jetés, car elle n'est pas valide d'un nombre décimal.

Par exemple, la clé pour ces tableaux sont des entiers:

array("13" => "b");
array("-13" => "b");                        // Negative, ok.

Mais la clé pour ces tableaux sont des chaînes de caractères:

array("13." => "b");
array("+13" => "b");                        // Positive, not ok.
array("-013" => "b");
array("0x1A" => "b");                       // Not converted to integers even though it's a valid hexadecimal number.
array("013" => "b");                        // Not converted to integers even though it's a valid octal number.
array("18446744073709551616" => "b");       // Not converted to integers as it can't fit into a 64-bit integer.

Qui plus est, selon le doc,

La taille d'un entier est dépend de la plateforme, bien que d'une valeur maximale d'environ deux milliards de dollars, c'est l'habituel (valeur 32 bits signés). Plates-formes 64 bits ont généralement une valeur maximale d'environ 9E18. PHP ne supporte pas des entiers non signés.

Donc, la clé pour ce tableau peut ou ne peut pas être un nombre entier , ça dépend de votre plate-forme.

array("60000000000" => "b");                // Array key could be integer or string, it can fit into a 64-bit (but not 32-bit) integer.

Pire encore, PHP tend à être buggy si l'entier est à proximité de la 231 = 2,147,483,648 limite (voir bug 51430, bug 52899). Par exemple, sur mon environnement local (PHP 5.3.8 sur XAMPP 1.7.7 sur Windows 7), var_dump(array("2147483647" => "b")) donne

array(1) {
    [2147483647]=>
    string(1) "b"
}   

mais sur cette démo en direct sur codepad (PHP 5.2.5, la même expression donne

array(1) {
    ["2147483647"]=>
    string(1) "b"
}

Donc, la clé est un nombre entier dans un environnement, mais une chaîne dans une autre, même si 2147483647 est valable signé de 32 bits entier.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X