in_array () e matriz multidimensional

243

Eu uso in_array()para verificar se existe um valor em uma matriz como abaixo,

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

//print_r($a);

mas e uma matriz multidimensional (abaixo) - como posso verificar se esse valor existe na matriz múltipla?

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

print_r($b);

ou eu não deveria estar usando in_array()quando se trata da matriz multidimensional?

laukok
fonte
1
A solução aceita funciona muito bem, mas pode levar a resultados indesejados ao fazer comparações não rigorosas devido ao malabarismo do tipo PHP. Veja: stackoverflow.com/a/48890256/1579327
Paolo
1
a resposta de jwueller e a minha são respostas corretas para sua pergunta. Propus uma solução alternativa que estende a função do jwueller para evitar um pitfail comum devido ao malabarismo de tipo do PHP ao fazer comparações não rigorosas.
Paolo
1
one liner:var_dump(array_sum(array_map(function ($tmp) {return in_array('NT',$tmp);}, $multiarray)) > 0);
Agnius Vasiliauskas
1
@AgniusVasiliauskas solução inteligente, mas tem problemas se a matriz de primeiro nível contiver um item que não seja uma matriz, por exemplo:$multiarray = array( "Hello", array("Mac", "NT"), array("Irix", "Linux"));
Paolo
1
@Paolo Ninguém impede que você expanda a função anônima de acordo com suas necessidades - neste caso, adicione a função anônima de check check se a variável $tmpfor uma matriz com is_array()função. Se não for um array - prossiga com um cenário diferente.
Agnius Vasiliauskas

Respostas:

473

in_array()não funciona em matrizes multidimensionais. Você pode escrever uma função recursiva para fazer isso por você:

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
fonte
1
obrigado. a função é elegante! adoro! obrigado. como posso saber se ele retorna verdadeiro ou falso, pois minha tela não mostra nada quando executo sua função? obrigado.
Laukok
14
Eu estava procurando por algo que fez isso, você só salvou-me de escrever minha própria :)
Liam W
1
Isso funciona muito bem. Então, como podemos pesquisar e exibir a chave da matriz? Por exemplo: $ b = matriz (1 => matriz ("Mac", "NT"), 3 => matriz ("Irix", "Linux"));
Rashad
2
@ O código D.Tate no StackOverflow é licenciado sob o cc by-sa 3.0 com a atribuição necessária (consulte o rodapé da página). Você pode apenas incluir um comentário com o link permanente para esta resposta.
jwueller
1
@blamb: Isso é muito intencional. É isso que torna a função recursiva (daí o _ranálogo print_r(), por exemplo). Ele desce em todas as matrizes aninhadas para procurar o valor até que não haja mais matrizes a serem encontradas. Dessa forma, você pode pesquisar matrizes de complexidade arbitrária em vez de apenas dois níveis de profundidade.
jwueller
56

Se você souber em qual coluna pesquisar, poderá usar array_search () e 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';
}

Essa ideia está na seção de comentários para array_search () no manual do PHP;

ethmz
fonte
15
Você também pode tentar: in_array ('value', array_column ($ arr, 'active'))
ekstro
1
Você precisa do PHP 5.5+ paraarray_column
meconroy 8/17
1
É possível obter o uid da sub-matriz correspondente neste exemplo? @ethmz
zipal_
isto é exatamente o que eu quero #
286
Isso é perfeito depois de uma longa solução encontrada!
Rohan Ashik
54

Isso também 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
fonte
3
Inteligente, eu gosto disso. Eu me pergunto como é o desempenho em comparação com o foreachloop.
James
1
Funcionou como um encanto.
Kemicofa ghost
1
Não me interpretem mal, eu gosto desta abordagem para este caso. No entanto, ele retornará uma correspondência positiva falsa quando json_encoding um $arrayque possui uma chave associativa correspondente $item. Sem mencionar o potencial de corresponder involuntariamente parte de uma sequência de caracteres quando houver aspas duplas na própria sequência. Eu confiaria apenas nessa função em situações pequenas / simples como essa pergunta.
precisa saber é o seguinte
Observe que isso falhará se $itemcontiver caracteres que estragam o primeiro parâmetro (expressão regular) depreg_match
Paolo
35

Isso fará isso:

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

in_arrayopera apenas em uma matriz unidimensional, portanto, você precisa fazer um loop sobre cada sub-matriz e executar in_arrayem cada uma.

Como outros observaram, isso será apenas para uma matriz bidimensional. Se você tiver mais matrizes aninhadas, uma versão recursiva seria melhor. Veja as outras respostas para exemplos disso.

Alan Geleynse
fonte
7
No entanto, isso funcionará apenas em uma dimensão. Você precisará criar uma função recursiva para verificar cada profundidade.
Metrobalderas
Eu executei o código, mas há um erro - Erro de análise: erro de análise em C: \ wamp \ www \ 000_TEST \ php \ php.in_array \ index.php na linha 21 - que é if (in_array ("Irix", $ value ) obrigado.
laukok
@lauthiamkok: Há uma )falta no final da linha mencionada.
usar o seguinte comando
Obrigado, eu corrigi minha resposta. É o que acontece quando digito muito rápido e não releio meu código.
Alan Geleynse
Você deve sempre chamar in_array()com o terceiro parâmetro definido como true. Confira aqui o porquê: stackoverflow.com/questions/37080581/…
Andreas
25

se sua matriz assim

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

Usa isto

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

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

rynhe
fonte
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
fonte
2
Embora esse código possa responder à pergunta, fornecer um contexto adicional a respeito de como e / ou por que ele resolve o problema melhoraria o valor a longo prazo da resposta.
Donald Duck
3
6 anos depois, me deu o que eu precisava. array_column()
precisa saber é o seguinte
resposta perfeita para matriz multidimensional
Roshan Sankhe
14

Ótima função, mas não funcionou para mim até eu adicionar if($found) { break; }oelseif

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

Para crianças multidimensionais: in_array('needle', array_column($arr, 'key'))

Para crianças unidimensionais: in_array('needle', call_user_func_array('array_merge', $arr))

Mohd Abdul Mujib
fonte
1
Arrumado! Obrigado @ 9ksoft
phaberest
E, diferentemente do array_column()método, o call_user_func_array('array_merge')método também funciona com matrizes filho baseadas em índice, +1
6

Você sempre pode serializar sua matriz multidimensional e fazer um strpos:

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

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

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

Vários documentos para as coisas que usei:


fonte
1
Isto é errado. Sua função também será verdadeira se a string de pesquisa estiver contida em algum valor de matriz (encontrará "Irix" em "mytoll Irixus").
Mdunisch
Eu consertei minha resposta. @ user3351722
dessa forma, pode ser corrigido um problema quando não houver mais ninguém (vale exclusivo), e ele deve 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 não acho que alguém no Stack Overflow publique código se não quiser que ele seja compartilhado. Sinta-se livre para usar qualquer código deste site para qualquer coisa. Normalmente, adiciono um comentário uma linha acima do snippet de código que diz "Thanks Stack Overflow" e colo o URL do qual encontrei o código.
1
Resposta interessante, definitivamente funciona em certas situações, mas não em todas.
MKN Web Solutions
4

Desde o PHP 5.6, existe uma solução melhor e mais limpa para a resposta original:

Com uma matriz multidimensional como esta:

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

Podemos usar o operador splat :

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

Se você tiver chaves de seqüência de caracteres como esta:

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

Você precisará usar array_valuespara evitar o erro Cannot unpack array with string keys:

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

A solução aceita (no momento da redação) 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;
}

Está perfeitamente correto, mas pode ter um comportamento não intencional ao fazer uma comparação fraca (o parâmetro $strict = false).

Devido ao malabarismo de tipos do PHP ao comparar valores de tipos diferentes,

"example" == 0

e

0 == "example"

Avalia trueporque "example"é intconvertido e transformado em 0.

(Veja Por que o PHP considera 0 igual a uma string? )

Se esse não for o comportamento desejado , pode ser conveniente converter valores numéricos para string antes de fazer uma comparação não estrita:

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

Esta é a primeira função deste tipo que eu encontrei no manual php para in_array . As funções nas seções de comentários nem sempre são as melhores, mas se isso não funcionar, você também pode procurar :)

<?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
fonte
A solução da elusiva é melhor, já que é apenas para matrizes
Gazillion
1

Aqui está minha proposição baseada na solução json_encode () com:

  • opção sem distinção entre maiúsculas e minúsculas
  • retornando a contagem em vez de verdadeiro
  • em qualquer lugar das matrizes (chaves e valores)

Se a palavra não for encontrada, ainda retornará 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 que ajude.

Meloman
fonte
Observe que esta função também combina com substrings : ex 00into 10000ou lointo Hello. Além disso, falhará se a agulha contiver qualquer caractere que json_encodeescape , como aspas duplas.
Paolo
Claro que depende do que você fará, mas para mim essa solução tem execução rápida e é suficiente.
Meloman
1

Eu acredito que você pode usar array_key_exists hoje em dia:

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

Eu estava procurando por uma função que me permitisse procurar por strings e matrizes (como agulha) na matriz (palheiro), então adicionei à resposta por @jwueller .

Aqui está o meu 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;
}
FreshSnow
fonte
0

Também funciona criando primeiro um novo array unidimensional a partir do original.

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

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

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

Versão mais curta, para matrizes multidimensionais criadas com base nos conjuntos de resultados do banco de dados.

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

Retornará se a matriz $ os_list contiver 'XP' no campo os_version.

andreszs
fonte
0

Encontrei uma solução simples muito pequena:

Se sua matriz for:

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

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

)

então o código será como:

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

Eu usei esse método funciona para qualquer número de aninhados e não requer hackers

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

Tente por favor:

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

Não tenho certeza sobre a necessidade, mas isso pode funcionar para sua exigência

sparco
fonte
2
Como a pesquisa nas chaves da matriz faria alguma coisa? $bAs chaves da matriz são apenas números inteiros ... não há chaves especificadas nessas matrizes ... e array_keys($b["irix"])apenas lançará um erro, porque $b["irix"]não existe.
Ben D