in_array () i tablica wielowymiarowa


243

Używam in_array()do sprawdzania, czy wartość istnieje w tablicy takiej jak poniżej,

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

//print_r($a);

ale co z tablicą wielowymiarową (poniżej) - jak mogę sprawdzić tę wartość, czy istnieje w tablicy wielowymiarowej?

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

print_r($b);

czy nie powinienem używać, in_array()jeśli chodzi o tablicę wielowymiarową?


1
Zaakceptowane rozwiązanie działa świetnie, ale może prowadzić do niezamierzonych rezultatów, gdy wykonujemy nieścisłe porównania ze względu na żonglerkę typu PHP. Zobacz: stackoverflow.com/a/48890256/1579327
Paolo

1
zarówno odpowiedź jwuellera, jak i moja są poprawnymi odpowiedziami na twoje pytanie. Zaproponowałem alternatywne rozwiązanie, które rozszerza funkcję jwuellera , aby uniknąć typowej pułapki z powodu żonglowania typami PHP podczas wykonywania niejednoznacznych porównań.
Paolo

1
jeden liniowiec:var_dump(array_sum(array_map(function ($tmp) {return in_array('NT',$tmp);}, $multiarray)) > 0);
Agnius Vasiliauskas

1
@AgniusVasiliauskas sprytne rozwiązanie, ale ma problemy, jeśli tablica pierwszego poziomu zawiera element, który nie jest tablicą, np .:$multiarray = array( "Hello", array("Mac", "NT"), array("Irix", "Linux"));
Paolo

1
@Paolo Nikt nie powstrzymuje cię przed rozszerzeniem funkcji anonimowej zgodnie z Twoimi potrzebami - w tym przypadku dodaj zaznacz funkcję anonimową, jeśli zmienna $tmpjest tablicą z is_array()funkcją. Jeśli nie tablica - przejdź do innego scenariusza.
Agnius Vasiliauskas

Odpowiedzi:


473

in_array()nie działa na tablicach wielowymiarowych. Możesz napisać funkcję rekurencyjną, aby to zrobić za Ciebie:

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

Stosowanie:

$b = array(array("Mac", "NT"), array("Irix", "Linux"));
echo in_array_r("Irix", $b) ? 'found' : 'not found';

1
Dziękuję Ci. funkcja jest elegancka! kocham to! dzięki. skąd mam wiedzieć, że zwraca wartość prawda lub fałsz, ponieważ mój ekran nie pokazuje niczego po uruchomieniu funkcji? dzięki.
laukok

14
Szukałem czegoś, co to zrobiło, właśnie uratowałeś mnie przed pisaniem własnych :)
Liam W

1
Działa świetnie. Jak więc możemy wyszukiwać i wyświetlać klucz tablicy? Na przykład: $ b = tablica (1 => tablica („Mac”, „NT”), 3 => tablica („Irix”, „Linux”));
Rashad,

2
@ D.Tate Code na StackOverflow jest licencjonowany na licencji CC by-sa 3.0 z wymaganą atrybucją (patrz stopka strony). Możesz po prostu dołączyć komentarz z linkiem do tej odpowiedzi.
jwueller

1
@blamb: To bardzo celowe. To sprawia, że ​​funkcja jest rekurencyjna (stąd _ranalogiczne do print_r(), na przykład). Opada na wszystkie zagnieżdżone tablice, aby wyszukać wartość, dopóki nie będzie już więcej tablic do znalezienia. W ten sposób możesz przeszukiwać tablice o dowolnej złożoności zamiast głębokości zaledwie dwóch poziomów.
jwueller

56

Jeśli wiesz, w której kolumnie szukać, możesz użyć array_search () i 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';
}

Ten pomysł znajduje się w sekcji komentarzy do array_search () w podręczniku PHP;


15
Możesz także spróbować: in_array ('wartość', array_column ($ arr, 'active'))
ekstro

1
Potrzebujesz PHP array_column
5.5+

1
Czy w tym przykładzie można uzyskać identyfikator UID dopasowanej podgrupy? @ethmz
zipal_

właśnie tego chcę
Juned Ansari,

Jest to idealne rozwiązanie po długim znalezieniu tego rozwiązania!
Rohan Ashik

54

To też zadziała.

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

Stosowanie:

if(in_array_r($item , $array)){
    // found!
}

3
Sprytne, podoba mi się to. Zastanawiam się, jak wygląda wydajność w porównaniu z foreachpętlą.
James

1
Działa jak urok.
kemicofa ghost

1
Nie zrozum mnie źle, podoba mi się to podejście w tej sprawie. Zwróci jednak fałszywie dodatnie dopasowanie, gdy json_encoding $arrayma pasujący klucz asocjacyjny $item. Nie wspominając już o możliwości niezamierzonego dopasowania części łańcucha, gdy w samym łańcuchu występuje podwójny cudzysłów. Ufałbym tej funkcji tylko w małych / prostych sytuacjach, takich jak to pytanie.
mickmackusa,

Pamiętaj, że to się nie powiedzie, jeśli $itemzawiera znaki, które psują pierwszy parametr (wyrażenie regularne)preg_match
Paolo

35

To zrobi to:

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

in_arraydziała tylko na jednowymiarowej tablicy, więc musisz zapętlić każdą pod-tablicę i uruchomić in_arrayna każdej z nich.

Jak zauważyli inni, dotyczy to tylko dwuwymiarowej tablicy. Jeśli masz więcej zagnieżdżonych tablic, lepsza byłaby wersja rekurencyjna. Przykłady tego można znaleźć w innych odpowiedziach.


7
Działa to jednak tylko w jednym wymiarze. Musisz utworzyć funkcję rekurencyjną, aby sprawdzić każdą głębokość.
metrobalderas

uruchomiłem kod, ale wystąpił błąd - Błąd analizy: błąd analizy: C: \ wamp \ www \ 000_TEST \ php \ php.in_array \ index.php w linii 21 - czyli if (in_array ("Irix", $ value ) dzięki.
laukok

@lauthiamkok: )Brakuje na końcu wspomnianej linii.
jwueller

Dzięki, naprawiłem swoją odpowiedź. Tak się dzieje, gdy piszę zbyt szybko i nie czytam ponownie kodu.
Alan Geleynse,

Zawsze powinieneś dzwonić in_array()z trzecim parametrem ustawionym na true. Sprawdź tutaj, dlaczego: stackoverflow.com/questions/37080581/...
Andreas

25

jeśli twoja tablica tak

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

Użyj tego

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

przykład: echo in_multiarray("22", $array,"Age");


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

2
Chociaż ten kod może odpowiedzieć na pytanie, zapewnienie dodatkowego kontekstu dotyczącego tego, jak i / lub dlaczego rozwiązuje problem, poprawiłoby długoterminową wartość odpowiedzi.
Kaczor Donald

3
6 lat później dało mi to, czego potrzebuję. array_column()
NappingRabbit

idealna odpowiedź na tablicę wielowymiarową
Roshan Sankhe

14

Świetna funkcja, ale nie działała dla mnie, dopóki nie dodałem if($found) { break; }doelseif

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

11

Dla dzieci wielowymiarowych: in_array('needle', array_column($arr, 'key'))

Dla dzieci jednowymiarowych: in_array('needle', call_user_func_array('array_merge', $arr))


1
Schludny! Dzięki @ 9ksoft
phaberest

I w przeciwieństwie do array_column()metody, call_user_func_array('array_merge')metoda ta działa również z podrzędnymi tablicami indeksowymi, +1

6

Zawsze możesz serializować swoją wielowymiarową tablicę i wykonać strpos:

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

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

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

Różne dokumenty dotyczące rzeczy, których użyłem:


1
To jest źle. Twoja funkcja da również prawdę, jeśli szukany ciąg znaków zawiera jakąś wartość tablicową (znajdzie „Irix” w „mytoll Irixus”).
mdunisch

Naprawiłem swoją odpowiedź. @ user3351722

w ten sposób można naprawić problem, gdy nie ma już jednego (unikalna dolina), a jego dynamika .. podobnie jak ten $ in_arr = (bool) strpos (serialize ($ user_term_was_downloaded), 's: 3: "tid"; s: 2: "'. $ Value-> tid.'"; ');
Anees Hikmat Abu Hmiad

2
@ I - II nie sądzę, aby ktokolwiek na stosie przepełnienia stosu opublikowałby kod, gdyby nie chciał, aby został udostępniony. Możesz użyć dowolnego kodu na tej stronie do czegokolwiek. Zazwyczaj dodaję jeden wiersz powyżej fragmentu kodu z napisem „Przepełnienie stosu dzięki”, a następnie wklejam adres URL, z którego znalazłem kod.

1
Interesująca odpowiedź, zdecydowanie działa w pewnych sytuacjach, ale nie we wszystkich.
MKN Web Solutions

4

Od PHP 5.6 jest lepszy i czystszy rozwiązanie dla oryginalnej odpowiedzi:

Dzięki takiej wielowymiarowej tablicy:

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

Możemy użyć operatora splat :

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

Jeśli masz takie klucze łańcuchowe:

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

Będziesz musiał użyć array_values, aby uniknąć błędu Cannot unpack array with string keys:

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

2

Przyjętego rozwiązania (w momencie pisania) przez 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;
}

Jest całkowicie poprawny, ale może mieć niezamierzone zachowanie podczas słabego porównywania (parametr $strict = false).

Z powodu żonglowania typami PHP podczas porównywania wartości różnych typów

"example" == 0

i

0 == "example"

Ocenia, trueponieważ "example"jest rzutowany inti przekształcany w 0.

(Zobacz Dlaczego PHP uważa 0 za ciąg znaków? )

Jeśli nie jest to pożądane zachowanie , wygodne może być rzutowanie wartości liczbowych na łańcuch przed wykonaniem nieścisłego porównania:

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

1

Jest to pierwsza funkcja tego typu, którą znalazłem w podręczniku php dla in_array . Funkcje w sekcjach komentarzy nie zawsze są najlepsze, ale jeśli to nie pomoże, możesz też tam zajrzeć :)

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

rozwiązanie nieuchwytne jest lepsze, ponieważ dotyczy tylko tablic
Gazillion

1

Oto moja propozycja oparta na rozwiązaniu json_encode () z:

  • opcja bez rozróżniania wielkości liter
  • zwracanie liczby zamiast prawdziwej
  • gdziekolwiek w tablicach (klucze i wartości)

Jeśli słowo nie zostanie znalezione, nadal zwraca 0 równe false .

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

Mam nadzieję, że to pomoże.


Zauważ, że ta funkcja pasuje również do podciągów : ex 00do 10000lub lodo Hello. Ponadto zawiedzie, jeśli igła zawiera dowolny znak, który json_encodeucieka , na przykład podwójne cudzysłowy.
Paolo

Oczywiście zależy to od tego, co zrobisz, ale dla mnie to rozwiązanie ma szybkie wykonanie i wystarczy.
Meloman

1

Wierzę, że w dzisiejszych czasach możesz po prostu używać array_key_exists :

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

1

Szukałem funkcji, która pozwoliłaby mi wyszukać zarówno łańcuchy, jak i tablice (jako igłę) w tablicy (stóg siana), więc dodałem do odpowiedzi @jwueller .

Oto mój kod:

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

0

Działa również, tworząc najpierw nowy jednowymiarowy Array z oryginalnego.

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

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

in_array($needle,$vector);

0

Krótsza wersja dla tablic wielowymiarowych utworzonych na podstawie zestawów wyników bazy danych.

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

Zwróci, jeśli tablica $ os_list zawiera „XP” w polu os_version.


0

Znalazłem naprawdę małe proste rozwiązanie:

Jeśli twoja tablica to:

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

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

)

wtedy kod będzie wyglądał następująco:

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

0

Użyłem tej metody działa dla dowolnej liczby zagnieżdżonych i nie wymaga hakowania

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

-1

Proszę spróbować:

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

Nie jestem pewien co do potrzeby, ale może to działać w zależności od potrzeb


2
W jaki sposób przeszukiwanie klawiszy macierzy może coś zrobić? $bKlucze tablic są tylko liczbami całkowitymi ... nie ma określonych kluczy w tych tablicach ... i array_keys($b["irix"])po prostu wyrzucą błąd, ponieważ $b["irix"]nie istnieje.
Ben D


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.