4

I made this function to search inside nested array but I keep getting null for this array:

$arr3 = [
    'first' => 1,
    'second' => 2,
    'third' => [
        'fourth' => 4,
    ]
];

/**
 * returns the key for the first found value
 *
 * @param $needle
 * @param array $haystack
 * @return false|int|string
 */
function array_search_value($needle, array $haystack) {

    $result = null;
    $found = array_search($needle, $haystack);

    if ( $found !== false ) {
        // end the recursion
        $result = $found;

    } else {
        foreach ($haystack as $key => $item) {
            if (is_array($item)) {
                array_search_value($needle, $item);
            } else {
                continue;
            }
        }
    }

    return $result;
}

var_dump(array_search_value(4, $arr3));

I can't figure it out what have I done wrong? The var_dump() result should be string "fourth".

3
  • 1
    In the for-loop you need to assign result to the recursive call Commented Feb 8, 2019 at 8:56
  • 5
    When you call a function recursively you must make sure to propagate the recursive call's return value back to the original caller: return array_search_value($needle, $item); Commented Feb 8, 2019 at 8:57
  • Yes... you were right.... the return statement was missing in recursive call.... Please someone make an answer so I can accept it. Commented Feb 8, 2019 at 8:59

5 Answers 5

3

If you find the thing you're looking for during recursion you're not really storing it anywhere. Here's my recommended approach:

$arr3 = [
    'first' => 1,
    'second' => 2,
    'third' => [
        'fourth' => 4,
    ]
];

/**
 * returns the key for the first found value
 *
 * @param $needle
 * @param array $haystack
 * @return null|array
 */
function array_search_value($needle, array $haystack) {

    $result = null;
    $found = array_search($needle, $haystack);

    if ( $found !== false ) {
        // end the recursion
        $result = [ $found ]; //Array will make sense in a bit

    } else {
        foreach ($haystack as $key => $item) {
            if (is_array($item)) {
                $found = array_search_value($needle, $item);
                if ($found !== null) {
                   return array_merge([$key],$found);
                }
            } else {
                continue;
            }
        }
    }

    return $result;
}

var_dump(array_search_value(4, $arr3));

The reason for returning an array is in case the subarray has the same key as the main array so you would be able to consistently retrieve the correct key by recursively accesssing the array index for each array entry returned.

Check out the code at: http://sandbox.onlinephpfunctions.com/code/085c949f660504010ed7ebb7a846e31b3a766d61

Here's an example as to why the returning of an array may be necessary:

If you consider the array:

$arr3 = [
    'a' => 1,
    'b' => 2,
    'c' => [
        'a' => 4,
    ],
    "d"=>[
        "a" => [
            "a" => 19    
        ]
    ]
];

If you're looking for 4 and not return an array you'll get back a but that will also be ambiguous because a contains 1 in the root array

http://sandbox.onlinephpfunctions.com/code/43c2f2dfa197400df1e5748e12f12e5346abed3e

You could modify the above to get all paths that lead to the given result if there are more than one.

function array_search_value_all($needle, array $haystack) {

    $result = [];
    $found = array_search($needle, $haystack);

    if ( $found !== false ) {
        // end the recursion
        $result[] = [ $found ]; //Array will make sense in a bit

    } else {
        foreach ($haystack as $key => $item) {
            if (is_array($item)) {
                $found = array_search_value($needle, $item);
                if ($found !== []) {
                   $result[] = array_merge([$key],$found);
                }
            } else {
                continue;
            }
        }
    }

    return $result;
}

array_search_value_all will return an array of all paths leading to that value.

Example: http://sandbox.onlinephpfunctions.com/code/fa4f5274703abb221f171c6e3ace5529594cdc8c

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

6 Comments

Something is wrong with your solution... I get an array with 2 values: array (size=2) 0 => string 'third' (length=5) 1 => string 'fourth' (length=6)
I guess it fine - he meant to return the whole path and not just the sub key. Nice one @apokryfos. Even if it is not what the OP meant :)
@dWinder actually in this answer you'll get the first path that leads to 4 . If you want to get all paths that lead to 4 that would be even more complicated. I'll try to provide an alternative that could get all
with apokryfs answer you can use the result to get the value directly from that nested array. for example I get the ['c', 'd'] and then it can be used to get that value programmatically
Just realised that so removed my commet
|
2

You are missing assign of the recursive call to you $result. You need to change:

if (is_array($item)) {
     array_search_value($needle, $item);

To: (notice that is the value not found keep searching and not just return)

if (is_array($item) ) {
    $i = array_search_value($needle, $item);
    if ($i)
        return $i;

3 Comments

it is enough just to write return array_search_value($needle, $item);!
Try case where $arr = ["a" => ["b" => 1], "c" => ["d" => 4]] and search for 4
Glad to help. Notice @apokryfos answer which is also good - but I don't know what you need then just choose your output
1

Just return the recursive call of array_search_value function:

    $arr3 = [
    'first' => 1,
    'second' => 2,
    'third' => [
        'fourth' => 4,
    ]
];

/**
 * returns the key for the first found value
 *
 * @param $needle
 * @param array $haystack
 * @return false|int|string
 */
function array_search_value($needle, array $haystack) {

    $result = null;
    $found = array_search($needle, $haystack);

    if ( $found !== false ) {
        // end the recursion
        $result = $found;

    } else {
        foreach ($haystack as $key => $item) {
            if (is_array($item)) {
                return array_search_value($needle, $item);
            } else {
                continue;
            }
        }
    }

    return $result;
}

var_dump(array_search_value(4, $arr3));

3 Comments

No good! what if the first array does not have the value but the second one has??
It will go recursively until it founds something... and if there is nothing it will return null
your question is a good base in case there are more than 1 array in depth
1

When you call a function recursively you must make sure to propagate the recursive call's return value back to the original caller:

    $arr3 = [
    'first' => 1,
    'second' => 2,
    'third' => [
        'fourth' => 4,
    ]
];

/**
 * returns the key for the first found value
 *
 * @param $needle
 * @param array $haystack
 * @return false|int|string
 */
function array_search_value($needle, array $haystack) {

    $result = null;
    $found = array_search($needle, $haystack);

    if ( $found !== false ) {
        // end the recursion
        $result = $found;

    } else {

        foreach ($haystack as $key => $item) {
            if (is_array($item)) { 
               $target = array_search_value($needle, $item);
                if ($target){
                    return $target;
                }
            } else {
                continue;
            }
        }

    }
    return $result;
}

var_dump(array_search_value(4, $arr3));

1 Comment

No good! what if the first array does not have the value but the second one has??
0
    $arr3 = [
    'first' => 1,
    'second' => 2,
    'third' => [
        'fourth' => 4,
    ]
];

/**
 * returns the key for the first found value
 *
 * @param $needle
 * @param array $haystack
 * @return false|int|string
 */
function array_search_value($needle, array $haystack) {

    $found = array_search($needle, $haystack);

    if ($found) {
        // put directly return here
        return $found;

    } else {
        foreach ($haystack as $key => $item) {
            if (is_array($item)) {
                return array_search_value($needle, $item);
            } else {
                continue;
            }
        }
    }

}

2 Comments

What is you add in addition to existing answers?
Maybe, but it is not answer the OP problem

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.