in_array () et tableau multidimensionnel

243

J'utilise in_array()pour vérifier si une valeur existe dans un tableau comme ci-dessous,

$a = array("Mac", "NT", "Irix", "Linux");
if (in_array("Irix", $a)) 
{
    echo "Got Irix";
}

//print_r($a);

mais qu'en est-il d'un tableau multidimensionnel (ci-dessous) - comment puis-je vérifier cette valeur si elle existe dans le multi-tableau?

$b = array(array("Mac", "NT"), array("Irix", "Linux"));

print_r($b);

ou je ne devrais pas utiliser in_array()quand vient le tableau multidimensionnel?

laukok
la source
1
La solution acceptée fonctionne très bien mais peut conduire à des résultats inattendus lors de comparaisons non strictes en raison du jonglage de type PHP. Voir: stackoverflow.com/a/48890256/1579327
Paolo
1
la réponse de jwueller et la mienne sont des réponses correctes à votre question. J'ai proposé une solution alternative qui étend la fonction de jwueller afin d'éviter un piège commun dû au jonglage de type PHP lors de comparaisons non strictes.
Paolo
1
un paquebot:var_dump(array_sum(array_map(function ($tmp) {return in_array('NT',$tmp);}, $multiarray)) > 0);
Agnius Vasiliauskas
1
@AgniusVasiliauskas, une solution intelligente, mais qui a des problèmes si le tableau de premier niveau contient un élément qui n'est pas un tableau, par exemple:$multiarray = array( "Hello", array("Mac", "NT"), array("Irix", "Linux"));
Paolo
1
@Paolo Personne ne vous empêche d'étendre la fonction anonyme en fonction de vos besoins - dans ce cas, ajoutez une fonction anonyme si la variable $tmpest un tableau avec is_array()fonction. Si ce n'est pas un tableau, procédez avec un scénario différent.
Agnius Vasiliauskas

Réponses:

473

in_array()ne fonctionne pas sur les tableaux multidimensionnels. Vous pouvez écrire une fonction récursive pour le faire pour vous:

function in_array_r($needle, $haystack, $strict = false) {
    foreach ($haystack as $item) {
        if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
            return true;
        }
    }

    return false;
}

Usage:

$b = array(array("Mac", "NT"), array("Irix", "Linux"));
echo in_array_r("Irix", $b) ? 'found' : 'not found';
jwueller
la source
1
Merci. la fonction est élégante! aimer! Merci. comment puis-je savoir qu'il retourne vrai ou faux car mon écran ne montre rien lorsque j'exécute votre fonction? Merci.
laukok
14
Je cherchais quelque chose qui a fait ça, vous venez de m'empêcher d'écrire le mien :)
Liam W
1
Cela fonctionne très bien. Alors, comment pouvons-nous rechercher et afficher la clé du tableau? Par exemple: $ b = array (1 => array ("Mac", "NT"), 3 => array ("Irix", "Linux"));
Rashad
2
@ D.Tate Code sur StackOverflow est autorisé sous cc by-sa 3.0 avec attribution requise (voir pied de page). Vous pouvez simplement inclure un commentaire avec le lien permanent vers cette réponse.
jwueller
1
@blamb: C'est très intentionnel. C'est ce qui rend la fonction récursive (d'où le _r, analogue à print_r(), par exemple). Il descend dans tous les tableaux imbriqués pour rechercher la valeur jusqu'à ce qu'il n'y ait plus de tableaux à trouver. De cette façon, vous pouvez rechercher dans des tableaux de complexité arbitraire au lieu de seulement deux niveaux de profondeur.
jwueller
56

Si vous connaissez la colonne à rechercher, vous pouvez utiliser array_search () et array_column ():

$userdb = Array
(
    (0) => Array
        (
            ('uid') => '100',
            ('name') => 'Sandra Shush',
            ('url') => 'urlof100'
        ),

    (1) => Array
        (
            ('uid') => '5465',
            ('name') => 'Stefanie Mcmohn',
            ('url') => 'urlof5465'
        ),

    (2) => Array
        (
            ('uid') => '40489',
            ('name') => 'Michael',
            ('url') => 'urlof40489'
        )
);

if(array_search('urlof5465', array_column($userdb, 'url')) !== false) {
    echo 'value is in multidim array';
}
else {
    echo 'value is not in multidim array';
}

Cette idée est dans la section commentaires de array_search () dans le manuel PHP;

ethmz
la source
15
Vous pouvez également essayer: in_array ('value', array_column ($ arr, 'active'))
ekstro
1
Vous avez besoin de PHP 5.5+ pourarray_column
meconroy
1
Est-il possible d'obtenir l'uid du sous-tableau correspondant dans cet exemple? @ethmz
zipal_
c'est exactement ce que je veux
Juned Ansari
C'est parfait après avoir longtemps trouvé cette solution!
Rohan Ashik
54

Cela fonctionnera aussi.

function in_array_r($item , $array){
    return preg_match('/"'.preg_quote($item, '/').'"/i' , json_encode($array));
}

Usage:

if(in_array_r($item , $array)){
    // found!
}
NassimPHP
la source
3
Intelligent, j'aime ça. Je me demande à quoi ressemblent les performances par rapport à la foreachboucle.
James
1
A fonctionné comme un charme.
kemicofa ghost
1
Ne vous méprenez pas, j'aime cette approche pour ce cas. Cependant, il retournera une fausse correspondance positive lors du json_encoding an $arrayqui a une clé associative qui correspond $item. Sans parler de la possibilité de faire correspondre involontairement une partie d'une chaîne lorsqu'il y a une citation double dans la chaîne elle-même. Je ne ferais confiance à cette fonction que dans des situations petites / simples comme cette question.
mickmackusa
Notez que cela échouera s'il $itemcontient des caractères qui bousillent le premier paramètre (expression régulière) depreg_match
Paolo
35

Cela le fera:

foreach($b as $value)
{
    if(in_array("Irix", $value, true))
    {
        echo "Got Irix";
    }
}

in_arrayfonctionne uniquement sur un tableau unidimensionnel, vous devez donc boucler sur chaque sous-tableau et exécuter in_arraysur chacun.

Comme d'autres l'ont noté, cela ne sera valable que pour un tableau à 2 dimensions. Si vous avez plus de tableaux imbriqués, une version récursive serait préférable. Voir les autres réponses pour des exemples de cela.

Alan Geleynse
la source
7
Cependant, cela ne fonctionnera que dans une seule dimension. Vous devrez créer une fonction récursive afin de vérifier chaque profondeur.
metrobalderas
j'ai exécuté le code mais il a une erreur - Erreur d'analyse: erreur d'analyse dans C: \ wamp \ www \ 000_TEST \ php \ php.in_array \ index.php sur la ligne 21 - qui est si (in_array ("Irix", $ value ) merci
laukok
@lauthiamkok: Il y a un )manquant à la fin de la ligne mentionnée.
jwueller
Merci, j'ai corrigé ma réponse. C'est ce qui arrive quand je tape trop vite et que je ne relis pas mon code.
Alan Geleynse
Vous devez toujours appeler in_array()avec le troisième paramètre défini sur true. Découvrez ici pourquoi: stackoverflow.com/questions/37080581/…
Andreas
25

si votre tableau comme celui-ci

$array = array(
              array("name" => "Robert", "Age" => "22", "Place" => "TN"), 
              array("name" => "Henry", "Age" => "21", "Place" => "TVL")
         );

Utilisez ceci

function in_multiarray($elem, $array,$field)
{
    $top = sizeof($array) - 1;
    $bottom = 0;
    while($bottom <= $top)
    {
        if($array[$bottom][$field] == $elem)
            return true;
        else 
            if(is_array($array[$bottom][$field]))
                if(in_multiarray($elem, ($array[$bottom][$field])))
                    return true;

        $bottom++;
    }        
    return false;
}

exemple : echo in_multiarray("22", $array,"Age");

rynhe
la source
21
$userdb = Array
(
    (0) => Array
        (
            ('uid') => '100',
            ('name') => 'Sandra Shush',
            ('url') => 'urlof100'
        ),

    (1) => Array
        (
            ('uid') => '5465',
            ('name') => 'Stefanie Mcmohn',
            ('url') => 'urlof5465'
        ),

    (2) => Array
        (
            ('uid') => '40489',
            ('name') => 'Michael',
            ('url') => 'urlof40489'
        )
);

$url_in_array = in_array('urlof5465', array_column($userdb, 'url'));

if($url_in_array) {
    echo 'value is in multidim array';
}
else {
    echo 'value is not in multidim array';
}
Mukesh Goyal
la source
2
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant la manière et / ou la raison pour laquelle il résout le problème améliorerait la valeur à long terme de la réponse.
Donald Duck
3
6 ans plus tard, cela m'a donné ce dont j'avais besoin. array_column()
NappingRabbit
réponse parfaite pour un tableau multidimensionnel
Roshan Sankhe
14

Grande fonction, mais cela n'a pas fonctionné pour moi jusqu'à ce que j'ajoute if($found) { break; }leelseif

function in_array_r($needle, $haystack) {
    $found = false;
    foreach ($haystack as $item) {
    if ($item === $needle) { 
            $found = true; 
            break; 
        } elseif (is_array($item)) {
            $found = in_array_r($needle, $item); 
            if($found) { 
                break; 
            } 
        }    
    }
    return $found;
}
Fernando
la source
11

Pour les enfants multidimensionnels: in_array('needle', array_column($arr, 'key'))

Pour les enfants unidimensionnels: in_array('needle', call_user_func_array('array_merge', $arr))

Mohd Abdul Mujib
la source
1
Soigné! Merci @ 9ksoft
phaberest
Et contrairement à la array_column()méthode, la call_user_func_array('array_merge')méthode fonctionne également avec les tableaux enfant basés sur l'index, +1
6

Vous pouvez toujours sérialiser votre tableau multidimensionnel et faire strpos:

$arr = array(array("Mac", "NT"), array("Irix", "Linux"));

$in_arr = (bool)strpos(serialize($arr),'s:4:"Irix";');

if($in_arr){
    echo "Got Irix!";
}

Divers documents pour les choses que j'ai utilisées:


la source
1
C'est faux. Votre fonction donnera également la valeur true si la chaîne de recherche est contenue dans une valeur de tableau (trouvera "Irix" dans "mytoll Irixus").
mdunisch
J'ai corrigé ma réponse. @ user3351722
de cette façon peut être corrigé un problème quand il n'y en a plus (val unique), et qu'il doit être dynamique. 2: "'. $ Value-> tid.'"; ');
Anees Hikmat Abu Hmiad
2
@ I - II ne pense pas que quiconque sur Stack Overflow publierait du code s'il ne voulait pas le partager. N'hésitez pas à utiliser n'importe quel code de ce site Web pour quoi que ce soit. J'ajoute généralement un commentaire une ligne au-dessus de l'extrait de code qui dit "Merci Stack Overflow", puis collez l'URL d'où j'ai trouvé le code.
1
Réponse intéressante, fonctionne certainement dans certaines situations, mais pas toutes.
MKN Web Solutions
4

Depuis PHP 5.6, il existe une solution meilleure et plus propre pour la réponse originale:

Avec un tableau multidimensionnel comme celui-ci:

$a = array(array("Mac", "NT"), array("Irix", "Linux"))

Nous pouvons utiliser l' opérateur splat :

return in_array("Irix", array_merge(...$a), true)

Si vous avez des clés de chaîne comme celle-ci:

$a = array("a" => array("Mac", "NT"), "b" => array("Irix", "Linux"))

Vous devrez utiliser array_valuespour éviter l'erreur Cannot unpack array with string keys:

return in_array("Irix", array_merge(...array_values($a)), true)
Fabien Salles
la source
2

La solution acceptée (au moment de la rédaction) par jwueller

function in_array_r($needle, $haystack, $strict = false) {
    foreach ($haystack as $item) {
        if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
            return true;
        }
    }

    return false;
}

Est parfaitement correct mais peut avoir un comportement inattendu lors d'une comparaison faible (le paramètre $strict = false).

En raison du type de jonglage de PHP lors de la comparaison de valeurs de type différent à la fois

"example" == 0

et

0 == "example"

Évalue truecar "example"est casté intet transformé en 0.

(Voir Pourquoi PHP considère-t-il que 0 est égal à une chaîne? )

Si ce n'est pas le comportement souhaité, il peut être pratique de convertir des valeurs numériques en chaîne avant d'effectuer une comparaison non stricte:

function in_array_r($needle, $haystack, $strict = false) {
    foreach ($haystack as $item) {

        if( ! $strict && is_string( $needle ) && ( is_float( $item ) || is_int( $item ) ) ) {
            $item = (string)$item;
        }

        if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
            return true;
        }
    }

    return false;
}
Paolo
la source
1

C'est la première fonction de ce type que j'ai trouvée dans le manuel php pour in_array . Les fonctions dans les sections de commentaires ne sont pas toujours les meilleures, mais si cela ne fait pas l'affaire, vous pouvez également y regarder :)

<?php
function in_multiarray($elem, $array)
    {
        // if the $array is an array or is an object
         if( is_array( $array ) || is_object( $array ) )
         {
             // if $elem is in $array object
             if( is_object( $array ) )
             {
                 $temp_array = get_object_vars( $array );
                 if( in_array( $elem, $temp_array ) )
                     return TRUE;
             }

             // if $elem is in $array return true
             if( is_array( $array ) && in_array( $elem, $array ) )
                 return TRUE;


             // if $elem isn't in $array, then check foreach element
             foreach( $array as $array_element )
             {
                 // if $array_element is an array or is an object call the in_multiarray function to this element
                 // if in_multiarray returns TRUE, than return is in array, else check next element
                 if( ( is_array( $array_element ) || is_object( $array_element ) ) && $this->in_multiarray( $elem, $array_element ) )
                 {
                     return TRUE;
                     exit;
                 }
             }
         }

         // if isn't in array return FALSE
         return FALSE;
    }
?>
Gazillion
la source
La solution d'
Elusive
1

Voici ma proposition basée sur la solution json_encode () avec:

  • option insensible à la casse
  • renvoyer le compte au lieu de vrai
  • n'importe où dans les tableaux (clés et valeurs)

Si le mot est introuvable, il renvoie toujours 0 égal à faux .

function in_array_count($needle, $haystack, $caseSensitive = true) {
    if(!$caseSensitive) {
        return substr_count(strtoupper(json_encode($haystack)), strtoupper($needle));
    }
    return substr_count(json_encode($haystack), $needle);
}

J'espère que ça aide.

Meloman
la source
Notez que cette fonction correspond également aux sous-chaînes : ex 00into 10000ou lointo Hello. De plus, cela échouera si l'aiguille contient un caractère qui json_encodes'échappe , comme des guillemets doubles.
Paolo
Bien sûr, cela dépend de ce que vous ferez, mais pour moi, cette solution a une exécution rapide et suffit.
Meloman
1

Je pense que vous pouvez simplement utiliser array_key_exists de nos jours:

<?php
$a=array("Mac"=>"NT","Irix"=>"Linux");
if (array_key_exists("Mac",$a))
  {
  echo "Key exists!";
  }
else
  {
  echo "Key does not exist!";
  }
?>
SrAxi
la source
1

Je cherchais une fonction qui me permettrait de rechercher à la fois des chaînes et des tableaux (comme aiguille) dans le tableau (botte de foin), j'ai donc ajouté à la réponse de @jwueller .

Voici mon code:

/**
 * Recursive in_array function
 * Searches recursively for needle in an array (haystack).
 * Works with both strings and arrays as needle.
 * Both needle's and haystack's keys are ignored, only values are compared.
 * Note: if needle is an array, all values in needle have to be found for it to
 * return true. If one value is not found, false is returned.
 * @param  mixed   $needle   The array or string to be found
 * @param  array   $haystack The array to be searched in
 * @param  boolean $strict   Use strict value & type validation (===) or just value
 * @return boolean           True if in array, false if not.
 */
function in_array_r($needle, $haystack, $strict = false) {
     // array wrapper
    if (is_array($needle)) {
        foreach ($needle as $value) {
            if (in_array_r($value, $haystack, $strict) == false) {
                // an array value was not found, stop search, return false
                return false;
            }
        }
        // if the code reaches this point, all values in array have been found
        return true;
    }

    // string handling
    foreach ($haystack as $item) {
        if (($strict ? $item === $needle : $item == $needle)
            || (is_array($item) && in_array_r($needle, $item, $strict))) {
            return true;
        }
    }
    return false;
}
FreshSnow
la source
0

Cela fonctionne aussi en créant d'abord un nouveau tableau unidimensionnel à partir de l'original.

$arr = array("key1"=>"value1","key2"=>"value2","key3"=>"value3");

foreach ($arr as $row)  $vector[] = $row['key1'];

in_array($needle,$vector);
Banzy
la source
0

Version plus courte, pour les tableaux multidimensionnels créés à partir d'ensembles de résultats de base de données.

function in_array_r($array, $field, $find){
    foreach($array as $item){
        if($item[$field] == $find) return true;
    }
    return false;
}

$is_found = in_array_r($os_list, 'os_version', 'XP');

Renvoie si le tableau $ os_list contient 'XP' dans le champ os_version.

andreszs
la source
0

J'ai trouvé une toute petite solution simple:

Si votre tableau est:

Array
(
[details] => Array
    (
        [name] => Dhruv
        [salary] => 5000
    )

[score] => Array
    (
        [ssc] => 70
        [diploma] => 90
        [degree] => 70
    )

)

alors le code sera comme:

 if(in_array("5000",$array['details'])){
             echo "yes found.";
         }
     else {
             echo "no not found";
          }
Dhruv Thakkar
la source
0

J'ai utilisé cette méthode fonctionne pour n'importe quel nombre de nids et ne nécessite pas de piratage

<?php
    $blogCategories = [
        'programing' => [
            'golang',
            'php',
            'ruby',
            'functional' => [
                'Erlang',
                'Haskell'
            ]
        ],
        'bd' => [
            'mysql',
            'sqlite'
        ]
    ];
    $it = new RecursiveArrayIterator($blogCategories);
    foreach (new RecursiveIteratorIterator($it) as $t) {
        $found = $t == 'Haskell';
        if ($found) {
           break;
        }
    }
Sr. Libre
la source
-1

S'il vous plaît essayez:

in_array("irix",array_keys($b))
in_array("Linux",array_keys($b["irix"])

Je ne suis pas sûr du besoin, mais cela pourrait fonctionner pour votre besoin

sparco
la source
2
Comment la recherche des clés du tableau ferait-elle quoi que ce soit? $bLes clés de tableau ne sont que des entiers ... il n'y a pas de clés spécifiées dans ces tableaux ... et array_keys($b["irix"])vont simplement générer une erreur, car elles $b["irix"]n'existent pas.
Ben D