33

I have a multidimensional array e.g. (this can be many levels deep):

$array = Array ( 
    [21] => Array ( ) 
    [24] => Array ( 
        [22] => Array ( ) 
        [25] => Array ( 
            [26] => Array ( ) 
        ) 
    ) 
) 

I am trying to loop through it to see if a certain key exists:

$keySearch = 22; // key searching for

function findKey($array, $keySearch) {
    foreach ($array as $item){
        if (isset($item[$keySearch]) && false === findKey($item[$keySearch], $item)){
            echo 'yes, it exists';
        }
    }
}

findKey($array, $keySearch);

But it finds nothing. Is there an error in the loop?

3
  • see this:: stackoverflow.com/a/2948985/350858 Commented Oct 17, 2013 at 7:47
  • Why not just use array_key_exists()? Commented Mar 15, 2023 at 16:07
  • @Haddock-san "Note: array_key_exists() will search for the keys in the first dimension only. Nested keys in multidimensional arrays will not be found." (see official docs) Commented Sep 7 at 10:18

9 Answers 9

55

array_key_exists() is helpful.

Then something like this:

function multiKeyExists(array $arr, $key) {

    // is in base array?
    if (array_key_exists($key, $arr)) {
        return true;
    }

    // check arrays contained in this array
    foreach ($arr as $element) {
        if (is_array($element)) {
            if (multiKeyExists($element, $key)) {
                return true;
            }
        }

    }

    return false;
}

Working example: http://codepad.org/GU0qG5su

Sign up to request clarification or add additional context in comments.

Comments

46

I played with your code to get it working :

function findKey($array, $keySearch)
{
    foreach ($array as $key => $item) {
        if ($key == $keySearch) {
            echo 'yes, it exists';
            return true;
        } elseif (is_array($item) && findKey($item, $keySearch)) {
            return true;
        }
    }
    return false;
}

6 Comments

Shouldnt: "if (isset( $array[$key] ) )" be: "if( is_array( $array[$key] ) )"? Obviously the $key is set in $array because the foreach is looping that array.
if (is_array($item)) findKey($item, $keySearch); - the return value of this call is lost.
I've edited to condense the if block. If this was my code, I'd rather rather use a single if with ||. *using parentheses as logic requires.
thanks for this...btw, from my testing, it's better to set the === operator for this to work properly.
To make it more complete, I would suggest also checking if $item isn't empty. This can avoid some problems down the road.
|
14

Here is a one line solution:

echo strpos(json_encode($array), $key) > 0 ? "found" : "not found";

This converts the array to a string containing the JSON equivalent, then it uses that string as the haystack argument of the strpos() function and it uses $key as the needle argument ($key is the value to find in the JSON string).

It can be helpful to do this to see the converted string: echo json_encode($array);

Be sure to enclose the needle argument in single quotes then double quotes because the name portion of the name/value pair in the JSON string will appear with double quotes around it. For instance, if looking for 22 in the array below then $key = '"22"' will give the correct result of not found in this array:

$array =
Array ( 
        21 => Array ( ), 
        24 => 
        Array ( 
            522 => Array ( ),
            25 =>
                Array ( 
                26 => Array ( ) 
            )
        )
    );

However, if the single quotes are left off, as in $key = "22" then an incorrect result of found will result for the array above.

EDIT: A further improvement would be to search for $key = '"22":'; just incase a value of "22" exists in the array. ie. 27 => "22" In addition, this approach is not bullet proof. An incorrect found could result if any of the array's values contain the string '"22":'

3 Comments

I would refuse a solution that works in the simplified case, but not when "special circumstances" occurs. If the values of the array may not contain all arbitrary values cause that might disturb your algorithm, the algorithm is miscrafted
Not agreed !! Because it will also return "found" if a value equals the searched key.
This solution is only correct for the OP's basic, minimal sample data. It is VERY easy for values in the array to cause this technique to give false positive results. I do not endorse this "hacky" solution. This answer makes no attempt to differentiate between "keys" and "values" in the json payload.
5
function findKey($array, $keySearch)
{
    // check if it's even an array
    if (!is_array($array)) return false;

    // key exists
    if (array_key_exists($keySearch, $array)) return true;

    // key isn't in this array, go deeper
    foreach($array as $key => $val)
    {
        // return true if it's found
        if (findKey($val, $keySearch)) return true;
    }

    return false;
}

// test
$array = Array ( 
    21 => Array ( 24 => 'ok' ),
    24 => Array ( 
        22 => Array ( 29 => 'ok' ),
        25 => Array ( 
            26 => Array ( 32 => 'ok' ) 
        )
    )
);

$findKeys = Array(21, 22, 23, 24, 25, 26, 27, 28, 29, 30);
foreach ($findKeys as $key)
{
    echo (findKey($array, $key)) ? 'found ' : 'not found ';
    echo $key.'<br>';
}

Comments

3

returns false if doesn't exists, returns the first instance if does;

function searchArray( array $array, $search )
{
    while( $array ) {
        if( isset( $array[ $search ] ) ) return $array[ $search ];
            $segment = array_shift( $array );
            if( is_array( $segment ) ) {
                if( $return = searchArray( $segment, $search ) ) return $return;
            }
        }
    }
    return false;
}

1 Comment

What if "false" is the value stored under the requested key? How to distinguish that? ;)
2

For sure some errors, is this roughly what you are after? (Untested code):

$keySearch=22; // key seraching for

function findKey($array, $keySearch) 
{ 
    // check whether input is an array
    if(is_array($array)
    {
       foreach ($array as $item)
       {
         if (isset($item[$keySearch]) || findKey($item, $keysearch) === true)
          {
            echo 'yes, it exists';
            return true;
          }
       }
    }
}

2 Comments

This method is missing a clear return statement for the case that the key does not exist
If the sought key is paired to a null value, a false negative result will be generated.
0

Here is one solution that finds and return the value of the key in any dimension array..

function findValByKey($arr , $keySearch){
    $out = null;
    if (is_array($arr)){
        if (array_key_exists($keySearch, $arr)){
            $out = $arr[$keySearch];
        }else{
            foreach ($arr as $key => $value){
                if ($out = self::findValByKey($value, $keySearch)){
                    break;
                }
            }
        }
    }
    return $out;
}

Comments

0

I did modified to return value of searched key:

function findKeyInArray($array, $keySearch, &$value)
{
    foreach ($array as $key => $item) {
        if ($key === $keySearch) {
            $value =  $item;
            break;
        } elseif (is_array($item)) {
            findKeyInArray($item, $keySearch,$value);
        }
    }
}
$timeZone = null;
findKeyInArray($request, 'timezone', $timeZone);

1 Comment

Welcome to SO! Please take a look at the other answers that were given before. Your approach is mentioned there already. In order to keep the site clear and make it easy to find answers, we try to avoid double answers.
0

This prints "Found":

$a = ["a"];
$a["a"] = [];
$a["a"]["b"] = ["c"];

$exists = $a["a"]["b"] ?? false;

if (is_array($exists))
echo "Found";
else
echo "Not Found";

While this prints "Not Found":

$a = ["a"];
$a["a"] = [];
$a["a"]["b"] = ["c"];

$exists = $a["a"]["c"] ?? false;

if (is_array($exists))
echo "Found";
else
echo "Not Found";

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.