in_array () та багатовимірний масив


243

Я використовую in_array()для перевірки, чи існує значення в масиві, як показано нижче,

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

//print_r($a);

а як щодо багатовимірного масиву (внизу) - як я можу перевірити це значення, чи існує воно в багатоманітному масиві?

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

print_r($b);

або я не повинен використовувати, in_array()коли йдеться про багатовимірний масив?


1
Прийняте рішення працює чудово, але може призвести до ненавмисних результатів при не строгих порівняннях через жонглювання типу PHP. Дивіться: stackoverflow.com/a/48890256/1579327
Паоло

1
і відповідь jwueller , і моя - правильні відповіді на ваше запитання. Я запропонував альтернативне рішення, яке розширює функцію jwueller , щоб уникнути загальної непрохідності через жонглювання типу PHP під час проведення не строгих порівнянь.
Паоло

1
один лайнер:var_dump(array_sum(array_map(function ($tmp) {return in_array('NT',$tmp);}, $multiarray)) > 0);
Агній Василіяускас

1
@AgniusVasiliauskas розумне рішення, але є проблеми, якщо масив першого рівня містить елемент, який не є масивом, напр .:$multiarray = array( "Hello", array("Mac", "NT"), array("Irix", "Linux"));
Паоло,

1
@Paolo Ніхто не заважає вам розширювати анонімну функцію відповідно до ваших потреб - у цьому випадку додайте реєстрацію анонімної функції, якщо змінна $tmpє масивом з is_array()функцією. Якщо не масив - приступайте до іншого сценарію.
Агній Василіяускас

Відповіді:


473

in_array()не працює над багатовимірними масивами. Ви можете написати рекурсивну функцію для цього:

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

Використання:

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

1
спасибі. функція елегантна! любити це! Дякую. як я можу знати, що він повертає справжнє або хибне, коли мій екран показує щось, коли я запускаю вашу функцію? Дякую.
laukok

14
Я шукав щось, що робив це, ви просто врятували мене від написання власного :)
Liam W

1
Це чудово працює. Тож як ми можемо шукати та відображати ключ масиву? Наприклад: $ b = array (1 => масив ("Mac", "NT"), 3 => масив ("Irix", "Linux"));
Рашад

2
@ D.Tate Код у StackOverflow ліцензується під cc by-sa 3.0 з необхідною атрибуцією (див. Нижній колонтитул сторінки). Ви можете просто включити коментар із постійною посиланням на цю відповідь.
jwueller

1
@blamb: Це дуже навмисно. Саме це робить функцію рекурсивною (отже _r, аналогічною print_r(), наприклад). Він спускається у всі вкладені масиви для пошуку значення, поки не знайдеться більше масивів. Таким чином, ви можете шукати масиви довільної складності, а не лише два рівні глибоко.
jwueller

56

Якщо ви знаєте, до якого стовпця шукати, ви можете використовувати array_search () та 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';
}

Ця ідея знаходиться у розділі коментарів для array_search () у посібнику PHP;


15
Ви також можете спробувати: in_array ('value', array_column ($ arr, 'active'))
ekstro

1
Вам потрібен PHP array_column
5.5+

1
Чи можливо отримати uid відповідного масиву підпорядкованих матеріалів у цьому прикладі? @ethmz
zipal_

саме цього я хочу
Juned Ansari

Це ідеально після давно знайденого рішення!
Рохан Ашик

54

Це теж буде працювати.

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

Використання:

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

3
Розумна, мені це подобається. Цікаво, як виглядає вистава в порівнянні з foreachциклом.
Джеймс

1
Працював як шарм.
kemicofa ghost

1
Не зрозумійте мене неправильно, мені подобається такий підхід у цій справі. Однак він поверне хибну позитивну відповідність, коли json_encoding an $arrayмає асоціативний ключ, який відповідає $item. Не кажучи вже про потенціал ненавмисного зіставлення частини рядка, коли в самому рядку є подвійна цитата. Я б довіряв цій функції лише в невеликих / простих ситуаціях, як це питання.
mickmackusa

Зауважте, що це не вдасться, якщо $itemмістять символи, які вкручують перший параметр (регулярний вираз)preg_match
Paolo

35

Це зробить це:

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

in_arrayпрацює лише на одновимірному масиві, тому вам потрібно перевести цикл на кожен підмасивний масив і запустити in_arrayна кожному.

Як зазначали інші, це буде лише для двовимірного масиву. Якщо у вас більше вкладених масивів, краще буде рекурсивна версія. Інші відповіді див. Для прикладів цього.


7
Однак це буде працювати лише в одному вимірі. Для перевірки кожної глибини вам доведеться створити рекурсивну функцію.
метробальдерас

Я запустив код, але він має помилку - помилка розбору: помилка розбору в C: \ wamp \ www \ 000_TEST \ php \ php.in_array \ index.php у рядку 21 - що є, якщо (in_array ("Irix", $ значення) ) дякую.
laukok

@lauthiamkok: У )кінці згаданого рядка є відсутність.
jwueller

Дякую, я виправив свою відповідь. Ось що відбувається, коли я набираю занадто швидко і не читаю код.
Алан Геленсе

Ви завжди повинні дзвонити in_array()з третім параметром, встановленим на true. Ознайомтеся з тим, чому: stackoverflow.com/questions/37080581/…
Андреас

25

якщо ваш масив такий

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

Використовуй це

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

приклад: 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
Хоча цей код може відповісти на питання, надаючи додатковий контекст щодо того, як та / або чому він вирішує проблему, покращить довгострокове значення відповіді.
Дональд Дак

3
Через 6 років це дало мені те, що мені потрібно. array_column()
NappingRabbit

ідеальна відповідь для багатовимірного масиву
Рошан Санкхе

14

Велика функція, але це не працювало для мене , поки я не додав if($found) { break; }доelseif

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

Для багатовимірних дітей: in_array('needle', array_column($arr, 'key'))

Для одномірних дітей: in_array('needle', call_user_func_array('array_merge', $arr))


1
Акуратно! Дякуємо @ 9ksoft
phaberest

І на відміну від array_column()методу, call_user_func_array('array_merge')метод також працює з дочірніми масивами на основі індексу, +1

6

Ви завжди можете серіалізувати свій багатовимірний масив і зробити strpos:

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

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

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

Різні документи для речей, які я використовував:


1
Це неправильно. Ваша функція також буде істинною, якщо рядок пошуку міститься в якомусь значенні масиву (знайде "Irix" в "Irix mytoll").
mdunisch

Я виправив свою відповідь. @ user3351722

таким чином можна вирішити проблему, коли немає більше однієї (унікальної долі), і її бути динамічною .. як це $ in_arr = (bool) strpos (серіалізувати ($ user_term_was_downloaded), 's: 3: "tid"; s: 2: "'. $ Value-> tid.'"; ');
Anees Hikmat Abu Hmiad

2
@ I - II, я не думаю, що хтось із Stack Overflow не надсилатиме поштовий індекс, якби вони не хотіли, щоб він був спільним. Не соромтеся використовувати будь-який код на цьому веб-сайті будь-що. Зазвичай я додаю коментар на один рядок над фрагментом коду, який пише "Спасибі переповнення стека", а потім вставляю URL-адресу, з якого я знайшов код.

1
Цікава відповідь, безумовно, працює в певних ситуаціях, але не у всіх.
Веб-рішення MKN

4

Оскільки PHP 5.6 є кращим і чистішим рішенням для оригінальної відповіді:

З таким багатовимірним масивом:

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

Ми можемо використовувати оператор splat :

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

Якщо у вас є такі рядкові клавіші:

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

Вам доведеться використовувати array_values, щоб уникнути помилки Cannot unpack array with string keys:

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

2

Прийняте рішення (на момент написання) по 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;
}

Цілком правильний, але може мати ненавмисну ​​поведінку, коли проводити слабке порівняння (параметр $strict = false).

Через жонглювання типу PHP при порівнянні значень різного типу

"example" == 0

і

0 == "example"

Оцінює за те, trueщо "example"кастинг intі перетворений на нього 0.

(Див. Чому PHP вважає 0 рівним рядку? )

Якщо це не бажана поведінка, може бути зручно вводити числові значення до рядків, перш ніж проводити не строге порівняння:

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

Це перша функція такого типу, яку я знайшов у керівництві php для in_array . Функції в розділах коментарів не завжди є найкращими, але якщо це не виконає трюк, ви можете зазирнути і туди :)

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

Рішення elusive є кращим, оскільки це лише для масивів
Gazillion

1

Ось моя пропозиція на основі рішення json_encode () з:

  • варіант нечутливий до випадку
  • повернення рахунку замість істинного
  • в будь-якому місці масивів (ключі та значення)

Якщо слово не знайдено, воно все одно поверне 0, що дорівнює 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);
}

Сподіваюся, це допомагає.


Зауважте, що ця функція також відповідає підрядкам : наприклад, 00в 10000або loв Hello. Крім того, не вдасться - голка містить будь-який символ, який json_encodeвтече , як подвійні лапки.
Паоло

Звичайно, залежить, що ви будете робити, але для мене це рішення має швидке виконання і цього достатньо.
Меломан

1

Я вважаю, що ви можете просто використовувати 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

Я шукав функцію, яка дозволила б мені шукати як рядки, так і масиви (як голки) в масиві (копиця сіна), тому я додав відповідь від @jwueller .

Ось мій код:

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

Це також працює, створюючи спочатку новий одновимірний масив з оригінального.

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

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

in_array($needle,$vector);

0

Коротша версія для багатовимірних масивів, створених на основі наборів результатів бази даних.

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

Повернеться, якщо масив $ os_list містить 'XP' у полі os_version.


0

Я знайшов дійсно невелике просте рішення:

Якщо ваш масив:

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

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

)

тоді код буде таким:

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

0

Я використовував цей метод працює для будь-якої кількості вкладених і не потребує злому

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

Будь ласка, спробуй:

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

Я не впевнений у необхідності, але це може працювати для вашої потреби


2
Як пошук клавіш масиву може щось робити? $bКлючі масиву 'є просто цілими числами ... в цих масивах немає вказаних ключів ... і array_keys($b["irix"])просто видасть помилку, оскільки її $b["irix"]немає.
Бен Д


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.