in_array () y matriz multidimensional

243

Yo uso in_array()para verificar si existe un valor en una matriz como a continuación,

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

//print_r($a);

pero ¿qué pasa con una matriz multidimensional (a continuación)? ¿Cómo puedo verificar ese valor si existe en la matriz múltiple?

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

print_r($b);

o no debería usar in_array()cuando se trata de la matriz multidimensional?

laukok
fuente
1
La solución aceptada funciona muy bien, pero puede conducir a resultados no deseados cuando se realizan comparaciones no estrictas debido al malabarismo de tipo PHP. Ver: stackoverflow.com/a/48890256/1579327
Paolo
1
Tanto la respuesta de jwueller como la mía son respuestas correctas a su pregunta. Propuse una solución alternativa que amplía la función de jwueller para evitar un error común debido al malabarismo de tipo PHP al hacer comparaciones no estrictas.
Paolo
1
var_dump(array_sum(array_map(function ($tmp) {return in_array('NT',$tmp);}, $multiarray)) > 0);
One
1
@AgniusVasiliauskas solución inteligente, pero tiene problemas si la matriz de primer nivel contiene un elemento que no es una matriz, por ejemplo:$multiarray = array( "Hello", array("Mac", "NT"), array("Irix", "Linux"));
Paolo
1
@Paolo Nadie le impide expandir la función anónima de acuerdo con sus necesidades; en este caso, agregue la verificación en la función anónima si la variable $tmpes una matriz con is_array()función. Si no es una matriz, proceda con un escenario diferente.
Agnius Vasiliauskas

Respuestas:

473

in_array()no funciona en matrices multidimensionales. Podría escribir una función recursiva para hacer eso por usted:

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;
}

Uso:

$b = array(array("Mac", "NT"), array("Irix", "Linux"));
echo in_array_r("Irix", $b) ? 'found' : 'not found';
jwueller
fuente
1
gracias. ¡la función es elegante! ¡quiéralo! Gracias. ¿Cómo puedo saber que devuelve verdadero o falso ya que mi pantalla no muestra nada cuando ejecuto su función? Gracias.
laukok
14
Estaba buscando algo que hiciera esto, me salvaste de escribir el mío :)
Liam W
1
Funciona muy bien Entonces, ¿cómo podemos buscar y mostrar la clave de matriz? Por ejemplo: $ b = array (1 => array ("Mac", "NT"), 3 => array ("Irix", "Linux"));
Rashad
2
@ D.Tate Code en StackOverflow tiene licencia bajo cc by-sa 3.0 con atribución requerida (ver pie de página). Puede incluir un comentario con el enlace permanente a esta respuesta.
jwueller
1
@blamb: Eso es muy intencional. Esto es lo que hace que la función sea recursiva (por lo tanto _r, análoga a print_r(), por ejemplo). Desciende a todas las matrices anidadas para buscar el valor hasta que no se encuentren más matrices. De esta manera, puede buscar en conjuntos de complejidad arbitraria en lugar de solo dos niveles de profundidad.
jwueller
56

Si sabe en qué columna buscar, puede usar array_search () y 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';
}

Esta idea está en la sección de comentarios de array_search () en el manual de PHP;

ethmz
fuente
15
También puede probar: in_array ('value', array_column ($ arr, 'active'))
ekstro
1
Necesita PHP 5.5+ paraarray_column
meconroy
1
¿Es posible obtener el uid de la submatriz coincidente en este ejemplo? @ethmz
zipal_
esto es exactamente lo que quiero
Juned Ansari
¡Esto es perfecto después de mucho encontrar esta solución!
Rohan Ashik
54

Esto también funcionará.

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

Uso:

if(in_array_r($item , $array)){
    // found!
}
NassimPHP
fuente
3
Inteligente, me gusta esto. Me pregunto cómo es el rendimiento en comparación con el foreachbucle.
James
1
Trabajado como un encanto.
kemicofa fantasma
1
No me malinterpreten, me gusta este enfoque para este caso. Sin embargo, devolverá una coincidencia de falso positivo cuando json_encoding un $arrayque tiene una clave asociativa que coincide $item. Sin mencionar el potencial de hacer coincidir involuntariamente parte de una cadena cuando hay una comilla doble en la cadena misma. Solo confiaría en esta función en situaciones pequeñas / simples como esta pregunta.
mickmackusa
Tenga en cuenta que esto fallará si $itemcontiene caracteres que arruinan el primer parámetro (expresión regular) depreg_match
Paolo
35

Esto lo hará:

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

in_arraysolo funciona en una matriz unidimensional, por lo que debe recorrer cada submatriz y ejecutarla in_arrayen cada una.

Como otros han señalado, esto solo será para una matriz bidimensional. Si tiene más matrices anidadas, una versión recursiva sería mejor. Vea las otras respuestas para ejemplos de eso.

Alan Geleynse
fuente
77
Sin embargo, esto solo funcionará en una dimensión. Tendrá que crear una función recursiva para verificar cada profundidad.
metrobalderas
ejecuté el código pero tiene un error - Error de análisis: error de análisis en C: \ wamp \ www \ 000_TEST \ php \ php.in_array \ index.php en la línea 21 - que es if (in_array ("Irix", $ value ) gracias.
laukok
@lauthiamkok: Falta una )al final de la línea mencionada.
jwueller
Gracias, arreglé mi respuesta. Eso es lo que sucede cuando escribo demasiado rápido y no vuelvo a leer mi código.
Alan Geleynse
Siempre debe llamar in_array()con el tercer parámetro establecido en true. Mira aquí por qué: stackoverflow.com/questions/37080581/…
Andreas
25

si tu matriz así

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

Utilizar este

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;
}

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

rynhe
fuente
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
fuente
2
Si bien este código puede responder la pregunta, proporcionar un contexto adicional con respecto a cómo y / o por qué resuelve el problema mejoraría el valor a largo plazo de la respuesta.
Pato Donald
3
6 años después, me dio lo que necesito. array_column()
NappingRabbit
respuesta perfecta para una matriz multidimensional
Roshan Sankhe
14

Gran función, pero no funcionó para mí hasta que agregué if($found) { break; }elelseif

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
fuente
11

Para niños multidimensionales: in_array('needle', array_column($arr, 'key'))

Para niños unidimensionales: in_array('needle', call_user_func_array('array_merge', $arr))

Mohd Abdul Mujib
fuente
1
¡Ordenado! Gracias @ 9ksoft
phaberest
Y a diferencia del array_column()método, el call_user_func_array('array_merge')método también funciona con matrices secundarias basadas en índices, +1
6

Siempre puede serializar su matriz multidimensional y hacer un strpos:

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

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

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

Varios documentos para las cosas que usé:


fuente
1
Eso está mal. Su función también dará verdadero si la cadena de búsqueda está contenida en algún valor de matriz (encontrará "Irix" en "mytoll Irixus").
mdunisch
He arreglado mi respuesta. @ user3351722
de esta manera se puede solucionar un problema cuando ya no hay uno (vale único), y debe ser dinámico ... como este $ in_arr = (bool) strpos (serialize ($ user_term_was_downloaded), 's: 3: "tid"; s: 2: "'. $ Value-> tid.'"; ');
Anees Hikmat Abu Hmiad
2
@ I - II no creo que nadie en Stack Overflow publique el código si no desea que se comparta. Siéntase libre de usar cualquiera de los códigos en este sitio web para cualquier cosa. Por lo general, agrego un comentario una línea sobre el fragmento de código que dice "Gracias desbordamiento de pila" y luego pego la URL de donde encontré el código.
1
Respuesta interesante, definitivamente funciona en ciertas situaciones, pero no en todas.
MKN Web Solutions
4

Desde PHP 5.6 hay una solución mejor y más limpia para la respuesta original:

Con una matriz multidimensional como esta:

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

Podemos usar el operador splat :

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

Si tiene teclas de cadena como esta:

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

Tendrá que usar array_valuespara evitar el error Cannot unpack array with string keys:

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

La solución aceptada (al momento de escribir) por 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;
}

Es perfectamente correcto pero puede tener un comportamiento no deseado al hacer una comparación débil (el parámetro $strict = false).

Debido al malabarismo de tipos de PHP al comparar valores de diferentes tipos, ambos

"example" == 0

y

0 == "example"

Evalúa trueporque "example"está fundido inty convertido en 0.

(Consulte ¿Por qué PHP considera que 0 es igual a una cadena? )

Si este no es el comportamiento deseado , puede ser conveniente convertir valores numéricos en una cadena antes de hacer una comparación no estricta:

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
fuente
1

Esta es la primera función de este tipo que encontré en el manual de php para in_array . Las funciones en las secciones de comentarios no siempre son las mejores, pero si no funciona, puedes mirar allí también :)

<?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
fuente
la solución de elusive es mejor ya que es solo para matrices
Gazillion
1

Aquí está mi propuesta basada en la solución json_encode () con:

  • opción insensible a mayúsculas y minúsculas
  • devolviendo el recuento en lugar de verdadero
  • en cualquier lugar de las matrices (claves y valores)

Si no se encuentra la palabra, aún devuelve 0 igual a falso .

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);
}

Espero eso ayude.

Meloman
fuente
Tenga en cuenta que esta función también coincide con las subcadenas : ex 00into 10000o lointo Hello. Además, fallará si la aguja contiene cualquier carácter que se json_encodeescape , como las comillas dobles.
Paolo
Por supuesto, depende de lo que haga, pero para mí esta solución tiene una ejecución rápida y es suficiente.
Meloman
1

Creo que puedes usar array_key_exists hoy en día:

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

Estaba buscando una función que me permitiera buscar cadenas y matrices (como aguja) en la matriz (pajar), así que agregué a la respuesta @jwueller .

Aquí está mi código:

/**
 * 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;
}
Nieve fresca
fuente
0

También funciona creando primero una nueva matriz unidimensional a partir de la original.

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

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

in_array($needle,$vector);
Banzy
fuente
0

Versión más corta, para matrices multidimensionales creadas en base a conjuntos de resultados de bases de datos.

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');

Volverá si la matriz $ os_list contiene 'XP' en el campo os_version.

andreszs
fuente
0

Encontré una solución simple muy pequeña:

Si su matriz es:

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

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

)

entonces el código será como:

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

Utilicé este método para cualquier número de anidados y no requiere piratería

<?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
fuente
-1

Por favor, inténtalo:

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

No estoy seguro acerca de la necesidad, pero esto podría funcionar para su requerimiento

sparco
fuente
2
¿Cómo haría algo la búsqueda de las teclas de matriz? $bLas claves de la matriz son solo enteros ... no hay claves específicas en estas matrices ... y array_keys($b["irix"])solo arrojarán un error, porque $b["irix"]no existe.
Ben D