7
$temp = array();
function show_keys($ar)
{
    foreach ($ar as $k => $v )
    {
        $temp[] = $k;
        if (is_array($ar[$k]))
        {
            show_keys ($ar[$k]);
        }
    }

    return $temp;
}

I tried using that function but it still only returns the first key.

2
  • This recursion is infinite in many cases. Commented Oct 6, 2010 at 13:29
  • 2
    A note on style: Don't call variables temp or tmp, especially in the global namespace, that leads to confusion. Names should be descriptive; call it keys, since that's what it contains. Commented Oct 6, 2010 at 13:31

9 Answers 9

11

Using SPL, looping over the keys is quite easy (store them in another array if you wish):

<?php
$arr = array_fill(0,8,range(0,3));
var_dump($arr);
foreach( new RecursiveIteratorIterator(
    new RecursiveArrayIterator($arr),
    RecursiveIteratorIterator::SELF_FIRST)
  as $key => $value){
        var_dump($key);
}
?>
Sign up to request clarification or add additional context in comments.

Comments

6

I see a lot of overly complicated solutions here....

function array_keys_r($array) {
  $keys = array_keys($array);

  foreach ($array as $i)
    if (is_array($i))
      $keys = array_merge($keys, array_keys_r($i));

  return $keys;
}

1 Comment

This solution loses the correct order of the keys.
5

The main problem is that you are throwing away the results of the recursive show_keys() calls. You don't do anything with the return value.

Comments are inline.

function show_keys($ar)
{
    // Create new temp array inside function so each recursive call gets
    // a separate instance.
    $temp = array();

    foreach ($ar as $k => $v )
    {
        $temp[] = $k;

        // Use $v instead of $ar[$k].
        if (is_array($v))
        {
            // Combine results of recursive show_keys with $temp.
            $temp = array_merge($temp, show_keys($v));
        }
    }

    return $temp;
}

Comments

2

This might do the trick?

You'd have to either bring in $temp as a global, or pick up the returned value from each recursion. And we'd want to avoid global variables, so we merge the values from each recursion call with previous gathered values.

function show_keys($ar)
{
    $temp = array();
    foreach ($ar as $k => $v )
    {
        $temp[] = $k;
        if (is_array($ar[$k]))
        {
            $temp = array_merge(show_keys ($ar[$k]), $temp);
        }
    }

    return $temp;
}

Comments

2

The question is ambiguous because you did not specify your input and expected output.

Consider this example array:

$array = [
    'first' => [
        'second' => [
            'third' => 'three',
        ],
        'deuxième' => 'two',
    ],
];

All of the other solutions so far provide a flattened one-dimensional array list of keys.

$keys = [
    'first',
    'second',
    'third',
    'deuxième',
];

However, I had a need for an array_keys_recursive function that would preserve the hierarchy.

$keys = [
    'first' => [
        'second' => [
            'third',
        ],
        'deuxième',
    ],
];

For anyone else searching for a similar need, here's my solution:

function array_keys_recursive(array $array) : array
{
    foreach ($array as $key => $value) {
        if (is_array($value)) {
            $index[$key] = array_keys_recursive($value);
        } else {
            $index []= $key;
        }
    }

    return $index ?? [];
}

Comments

2

As a supplement for other solutions there is possibility to return flattened array as a result but still keep the information about the tree. We can concatenate nested keys with parent. It could be useful for diffing with other arrays as you are distinguishing between same child keys but different parents

function array_keys_flatten_recursive($array, $parentKey = "") {
    $keys = array_keys($array);
    foreach ($array as $parentKey => $i)
      if (is_array($i)) {
        $nestedKeys = array_keys_flatten_recursive($i, $parentKey);
        foreach($nestedKeys as $index => $key) {
            $nestedKeys[$index] = $parentKey . "." . $key;
        }
        $keys = array_merge($keys, $nestedKeys);
      }
    return $keys;
}

Example:

$array = array(
    "one" => array(
        "one" => "lorem"
    ),
    "two" => array(
        "one" => "lorem"
    )
);


// result : array("one", "two", "one.one", "two.one")

Comments

0

Ofcause this function is infinite. But my task is to help you)

function show_keys($ar, $temp = array())
{    
    if (!empty($ar)) {
    foreach ($ar as $k => $v )
    {
        $temp[] = $k;
        if (is_array($ar[$k]))
        {
            $temp += show_keys($ar[$k], $temp);
        }
    }
    }

    return $temp;
}

Comments

0

Your array $temp is global. To make is accessible in the function you need :

global $temp;

at the start of the function.

Currently every invocation of the function is creating a new array with the name $temp and when you finally return from the function to its caller, the $temp you created in your first call is being returned, which has only the keys of your first level.

Note that using global variables is not good programming. You need to pass your array as argument to your recursive calls and modify the passed array by adding keys found in each iterations as Alexander and John have done.

2 Comments

No difference, seems like it was accepting the $temp in the first place.
You're probably right, that was one step closer to the solution.
0
    /**
     * @param array $array
     * @param string $devider
     * @return array
     */
    static public function arrayKeysRecursive(array $array, $devider='.'){
        $arrayKeys = [];
        foreach( $array as $key=>$value ){
            if( is_array($value) ){
                $rekusiveKeys = self::arrayKeysRecursive($value, $devider);
                foreach( $rekusiveKeys as $rekursiveKey ){
                    $arrayKeys[] = $key.$devider.$rekursiveKey;
                }
            }else{
                $arrayKeys[] = $key;
            }
        }
        return $arrayKeys;
    }

use it

arrayKeysRecursive(['one'=>['two'=>2, 'three'=>['four'=>4]]])

returns

['one.two', 'one.three.four']

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.