78

I need to search a multidimensional array for a specific value in any of the indexed subarrays.

In other words, I need to check a single column of the multidimensional array for a value. If the value exists anywhere in the multidimensional array, I would like to return true otherwise false

$my_array = array(    
    0 =>  array(  
        "name"   => "john",  
        "id"    =>  4  
    ),  
    1   =>  array(  
        "name" =>  "mark",  
        "id" => 152  
    ), 
    2   =>  array(  
        "name" =>  "Eduard",  
        "id" => 152  
    )
);

I would like to know the fastest and most efficient way to check if the array $my_array contains a value with the key "id". For example, if id => 152 anywhere in the multidimensional array, I would like true.

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
Rob
  • 899
  • 1
  • 6
  • 8
  • How to get the key numbers of the founds ids. e.g. the result will be the `1`,`2` if we search `id = 152`. @mickmackusa, @Rob – manas paul Sep 20 '22 at 07:58
  • Hi @mickmackusa, Can you please do it for me on the above array? Also is the `array_filter()` is faster to search than the `foreach`? Because i have larger array to search with the same key. – manas paul Sep 20 '22 at 10:15
  • @manas I assume you want [this](https://3v4l.org/XhoTS) Please remove all of the other comments that you have littered the page with. If you want multiple values, just don't return or break https://stackoverflow.com/a/16439674/2943403 – mickmackusa Sep 20 '22 at 13:13

18 Answers18

86

Nothing will be faster than a simple loop. You can mix-and-match some array functions to do it, but they'll just be implemented as a loop too.

function whatever($array, $key, $val) {
    foreach ($array as $item)
        if (isset($item[$key]) && $item[$key] == $val)
            return true;
    return false;
}
Dan Grossman
  • 51,866
  • 10
  • 112
  • 101
  • 1
    How to get the key numbers of the founds ids. e.g. the result will be the `1`,`2` if we search `id = 152`. @Dan Grossman – manas paul Sep 20 '22 at 08:00
38

The simplest way is this:

$my_array = array(    
    0 =>  array(  
        "name"   => "john",  
        "id"    =>  4  
    ),  
    1   =>  array(  
        "name" =>  "mark",  
        "id" => 152  
    ), 
    2   =>  array(  
        "name" =>  "Eduard",  
        "id" => 152  
    )
);

if (array_search(152, array_column($my_array, 'id')) !== FALSE) {
  echo 'FOUND!';
} else {
  echo 'NOT FOUND!';
}
Marcus
  • 51
  • 7
Jazzer
  • 1,035
  • 11
  • 7
33

** PHP >= 5.5

simply u can use this

$key = array_search(40489, array_column($userdb, 'uid'));

Let's suppose this multi dimensional array:

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

(1) => Array
    (
        (uid) => '5465',
        (name) => 'Stefanie Mcmohn',
        (pic_square) => 'urlof100'
    ),

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

$key = array_search(40489, array_column($userdb, 'uid'));
Shafiqul Islam
  • 5,570
  • 2
  • 34
  • 43
Manuel Pardo
  • 699
  • 7
  • 6
  • 5
    Why not simply `$ids = array_column($array, 'id', 'id');` and then `isset($ids[40489])`? – Elias Van Ootegem Aug 11 '16 at 15:33
  • Hey, do yo mind updating your answer and implement the comment from Elias? – leymannx Feb 16 '17 at 09:12
  • 4
    It is important to clarify for future researchers that `$key` may be `0` which is a falsey value. To know if `array_search()` found qualifying data, you must explicitly check if `$key !== false` or `$key === false` depending on your needs. – mickmackusa May 18 '20 at 10:26
25

Here is an updated version of Dan Grossman's answer which will cater for multidimensional arrays (what I was after):

function find_key_value($array, $key, $val)
{
    foreach ($array as $item)
    {
        if (is_array($item) && find_key_value($item, $key, $val)) return true;

        if (isset($item[$key]) && $item[$key] == $val) return true;
    }

    return false;
}
Joost
  • 10,333
  • 4
  • 55
  • 61
Friendly Code
  • 1,585
  • 1
  • 25
  • 41
  • 1
    Is it possible to do this, but without checking for a specific value? Return true if the key is empty, return false if the key is not empty. – TinyTiger May 16 '18 at 06:41
  • What if you don't have the actual value of $key to pass in? I want to search my entire array regardless of what the key is. – Cary Dec 10 '18 at 03:29
  • Sounds like you simply need the php function 'array_search' – Friendly Code Dec 12 '18 at 13:30
  • Because the input data is limited to a depth of 2 levels, it is unnecessary overhead to implement a recursive technique for this task. If this was a recursive task (and it isn't) then `array_walk_recursive()` would visit only the leaf nodes and eliminate the `is_array()` check. – mickmackusa May 18 '20 at 07:53
  • My array had a lot more levels than 2 – Friendly Code May 22 '20 at 15:20
8

If you have to make a lot of "id" lookups and it should be really fast you should use a second array containing all the "ids" as keys:

$lookup_array=array();

foreach($my_array as $arr){
    $lookup_array[$arr['id']]=1;
}

Now you can check for an existing id very fast, for example:

echo (isset($lookup_array[152]))?'yes':'no';
stewe
  • 41,820
  • 13
  • 79
  • 75
6

A good solution can be one provided by @Elias Van Ootegan in a comment that is:

$ids = array_column($array, 'id', 'id');
echo isset($ids[40489])?"Exist":"Not Exist";

I tried it and worked for me, thanks buddy.

Edited

Note: It will work in PHP 5.5+

Imran Qamer
  • 2,253
  • 3
  • 29
  • 52
3

TMTOWTDI. Here are several solutions in order of complexity.

(Short primer on complexity follows):O(n) or "big o" means worst case scenario where n means the number of elements in the array, and o(n) or "little o" means best case scenario. Long discrete math story short, you only really have to worry about the worst case scenario, and make sure it's not n ^ 2 or n!. It's more a measure of change in computing time as n increases than it is overall computing time. Wikipedia has a good article about computational aka time complexity.

If experience has taught me anything, it's that spending too much time optimizing your programs' little-o is a distinct waste of time better spent doing something - anything - better.

Solution 0: O(n) / o(1) complexity:

This solution has a best case scenario of 1 comparison - 1 iteration thru the loop, but only provided the matching value is in position 0 of the array. The worst case scenario is it's not in the array, and thus has to iterate over every element of the array.

foreach ($my_array as $sub_array) {
    if (@$sub_array['id'] === 152) {
        return true;
    }
}
return false;

Solution 1: O(n) / o(n) complexity:

This solution must loop thru the entire array no matter where the matching value is, so it's always going to be n iterations thru the array.

return 0 < count(
    array_filter(
        $my_array,
        function ($a) {
            return array_key_exists('id', $a) && $a['id'] == 152;
        }
    )
);

Solution 2: O(n log n) / o(n log n) complexity:

A hash insertion is where the log n comes from; n hash insertions = n * log n. There's a hash lookup at the end which is another log n but it's not included because that's just how discrete math works.

$existence_hash = [];
foreach ($my_array as $sub_array) {
    $existence_hash[$sub_array['id']] = true;
}
return @$existence_hash['152'];
amphetamachine
  • 27,620
  • 12
  • 60
  • 72
  • Casting `array_filter()`'s return value as `(bool)` will spare you having to count the results or compare against `0`. https://3v4l.org/2dVAu For anyone who is looking for the most efficient technique (and the OP is), using `array_filter()` will continue to iterate the input array even after a match is found so this will not be best way. – mickmackusa May 18 '20 at 07:50
  • [The `count()` call is an `O(1)` operation](https://stackoverflow.com/questions/4566314/php-what-is-the-complexity-i-e-o1-on-of-the-function-count), so there's no optimization by using a cast. Even if you write it as a short-circuiting `for` loop, the worst-case scenario would still be `O(n)` since the ID could not exist in `$my_array`. – amphetamachine May 18 '20 at 17:57
  • By converting to `(bool)` there is no function call and no conditional comparison on `array_filter()`'s return value so it is more direct and concise to convert to boolean type. DanGrossman's technique (though I'd be using curly braces for all language constructs) is going to be the best performer because it executes a conditional early return/break. I am sure you already know this; I am only stating this fact for researchers. Please add an explanation to your answer to role model better posting behaviors to newer users. – mickmackusa May 18 '20 at 21:46
2

I came upon this post looking to do the same and came up with my own solution I wanted to offer for future visitors of this page (and to see if doing this way presents any problems I had not forseen).

If you want to get a simple true or false output and want to do this with one line of code without a function or a loop you could serialize the array and then use stripos to search for the value:

stripos(serialize($my_array),$needle)

It seems to work for me.

marcnyc
  • 585
  • 1
  • 4
  • 17
1

As in your question, which is actually a simple 2-D array wouldn't it be better? Have a look-

Let say your 2-D array name $my_array and value to find is $id

function idExists($needle='', $haystack=array()){
    //now go through each internal array
    foreach ($haystack as $item) {
        if ($item['id']===$needle) {
            return true;
        }
    }
    return false;
}

and to call it:

idExists($id, $my_array);

As you can see, it actually only check if any internal index with key_name 'id' only, have your $value. Some other answers here might also result true if key_name 'name' also has $value

Anant
  • 534
  • 11
  • 40
  • This one is going to be one of the best performers on the page because it employs an early return and doesn't create a temporary array of `id` column data before checking for the needle. – mickmackusa May 18 '20 at 07:52
0

I don't know if this is better or worse for performance, but here is an alternative:

$keys = array_map(function($element){return $element['id'];}, $my_array);
$flipped_keys = array_flip($keys);
if(isset($flipped_keys[40489]))
{
    // true
}
Marcus
  • 51
  • 7
  • 1
    you might also be interested in array_column https://php.net/array_column – hakre Jul 11 '21 at 00:05
  • I saw, many have suggested it and I had tried it alone and couldn't get it to work until I saw Manuel's above. `$key = array_search(40489, array_column($userdb, 'uid'));`. I had already found my solution and just thought I'd share it. The array_search and array_column combo works perfect though. – Marcus Jul 11 '21 at 00:10
  • array_column and array_flip works equally. it was merely meant as a hint FYI, the array_map part can be replaced by it, the rest would be the same. Personally I would not combine it with array_search,but more like you did with array_flip. – hakre Jul 11 '21 at 00:14
0

array_column returns the values of a single column of an array and we can search for a specific value for those via in_array

if (in_array(152, array_column($my_array, 'id'))) {
    echo 'FOUND!';
} else {
    echo 'NOT FOUND!';
}
Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
transversus
  • 181
  • 2
  • `in_array()` is one of the least efficient ways to perform an array search. [@ImranQamer's answer](https://stackoverflow.com/a/41500450/2943403) will perform better because it searches keys instead of values. This answer is missing its educational explanation. – mickmackusa Nov 29 '22 at 21:51
0

You can create a queue of sub-arrays and loop each:

function existsKeyValue($myArray, $key, $value) {
    $queue = [$myArray]; //creating a queue of a single element, which is our outermost array

    //when we reach the count of the queue we looped all inner loops as well and failed to find the item
    for ($index = 0; $index < count($queue); $index++) {
        //Looping the current array, finding the key and the value
        foreach ($queue[$index] as $k => &$v) {
            //If they match the search, then we can return true
            if (($key === $k) && ($value === $v)) {
                return true;
            }
            //We need to make sure we did not already loop our current array to avoid infinite cycles
            if (is_array($v)) $queue[]=$v;
        }
    }
    return false;
}

$my_array = array(    
    0 =>  array(  
        "name"   => "john",  
        "id"    =>  4  
    ),  
    1   =>  array(  
        "name" =>  "mark",  
        "id" => 152  
    ), 
    2   =>  array(  
        "name" =>  "Eduard",  
        "id" => 152  
    )
);

echo var_dump(existsKeyValue($my_array, 'id', 152));

Lajos Arpad
  • 64,414
  • 37
  • 100
  • 175
0

Just use array_column as in below example:

$my_array = [
    [
        "name"  => "john",  
        "id"    =>  4  
    ],  
    [
        "name"  =>  "mark",  
        "id"    => 152  
    ], 
    [
        "name"  =>  "Eduard",  
        "id"    => 152  
    ]
];
var_dump(in_array(152, array_column($my_array, 'id'))); // true
MLFR2kx
  • 977
  • 7
  • 16
-1

Try with this below code. It should be working fine for any kind of multidimensional array search.

Here you can see LIVE DEMO EXAMPLE

function multi_array_search($search_for, $search_in) {
    foreach ($search_in as $element) {
        if ( ($element === $search_for) ){
            return true;
        }elseif(is_array($element)){
            $result = multi_array_search($search_for, $element);
            if($result == true)
                return true;
        }
    }
    return false;
}
Faisal
  • 4,591
  • 3
  • 40
  • 49
  • Notice how using recursion is not only needless overhead, it is doing unnecessary checks on first level elements. Proof that recursion is a bad choice for this question. https://3v4l.org/Aua2W – mickmackusa May 18 '20 at 07:24
-1

You can use this with only two parameter

function whatever($array, $val) {
    foreach ($array as $item)
        if (isset($item) && in_array($val,$item))
            return 1;
    return 0;
}
-1

different between isset vs array_key_exits What's the difference between isset() and array_key_exists()?

different between == vs === How do the PHP equality (== double equals) and identity (=== triple equals) comparison operators differ?

function specificValue(array $array,$key,$val) {
    foreach ($array as $item)
        if (array_key_exits($item[$key]) && $item[$key] === $val)
            return true;
    return false;
}
-2
function checkMultiArrayValue($array) {
        global $test;
        foreach ($array as $key => $item) {

            if(!empty($item) && is_array($item)) {
                checkMultiArrayValue($item);
            }else {
                if($item)
                 $test[$key] = $item;

            }
        }
        return $test;   
    }

 $multiArray = array(    
                0 =>  array(  
                      "country"   => "",  
                      "price"    => 4,  
                      "discount-price" => 0,  
               ),);

$test = checkMultiArrayValue($multiArray);
echo "<pre>"
print_r($test);

Will return array who have index and value

nageen nayak
  • 1,262
  • 2
  • 18
  • 28
  • This task does not benefit from a recursive technique. This code-only answer will do very little to educate/empower thousands of future researchers. When you post an answer always explain in plain English how it works and what advantages it has over other answers to this specific question. – mickmackusa May 18 '20 at 07:19
-3

I wrote the following function in order to determine if an multidimensional array partially contains a certain value.

function findKeyValue ($array, $needle, $value, $found = false){
    foreach ($array as $key => $item){
        // Navigate through the array completely.
        if (is_array($item)){
            $found = $this->findKeyValue($item, $needle, $value, $found);
        }

        // If the item is a node, verify if the value of the node contains
        // the given search parameter. E.G.: 'value' <=> 'This contains the value'
        if ( ! empty($key) && $key == $needle && strpos($item, $value) !== false){
            return true;
        }
    }

    return $found;
}

Call the function like this:

$this->findKeyValue($array, $key, $value);
  • 1
    There is no reason to use recursion for this task. The input array is just two levels deep. This is unnecessary convolution that should not be used for this problem. – mickmackusa May 18 '20 at 07:20