0

Say for example I have the following array:

$h = array (
    "app" => array (
        "level1" => array (
            "level2" => array (
                "level3" =>3
            ),
            "level4" => array (
                "level5" => 2
            )

        )
    )
);

What I wish to do is to create a string for every single sub-array found in here. For example, using the array above, the output would be:

Array
(
    [0] => Array
        (
            [app.level1.level2.level3] => 3
        )
    [1] => Array
        (
            [app.level1.level4.level5] => 2
        )
)

As you can see, each sub-array is concatenated with a '.' to represent the fact there is a child array with a value assigned given by the last node. Of course the only thing I can think of is to create a recursive function that could handle this, though this is where I'm having some trouble here. Here's what I started working on:

public static function buildString($array, $string ="") {
    foreach($array as $h => $k) {
        if(is_array($k)) {
            $string .= $h.".";
            return self::buildString($k, $string);  
        } else {
            $string .= $h;
            $j[] = array (
                $string => $k
            );      
            return $j;
        }
    }
}

Inputting the array given above within this method, I successfully get the first iteration:

Array
(
    [0] => Array
        (
            [app.level1.level2.level3] => 3
        )

)

And this is where I am at the moment and cannot seem to figure out how to do the rest of the array, or any size array for that matter.

Any hints//remarks would be appreciated.

1
  • You are doing depth first search, basically returning the first element you find and your program will exit. You need to modify your logic so that your function collects all the results from recursive calls. Commented Dec 31, 2014 at 3:17

3 Answers 3

1

You cannot return inside the foreach loop, you need to aggregate all of the recursive/non-recursive results and bubble them up. Something like this:

public static function buildString($array, $string ="") {
    $j = array();
    foreach($array as $h => $k) {
        if(is_array($k)) {
            $string .= $h.".";
            $j = array_merge($j, self::buildString($k, $string));  
        } else {
            $string .= $h;
            $j[] = array (
                $string => $k
            );      
        }
    }
    return $j;
}
Sign up to request clarification or add additional context in comments.

Comments

0

you can use array_walk() as a method:

$h = array (
    "app" => array (
        "level1" => array (
            "level2" => array (
                "level3" =>3
            ),
            "level4" => array (
                "level5" => 2
            )

        )
    )
);

$results = array();

function get_strings($item, $key, $old_key = null) {
    global $results;
    if(is_array($item)) {
        array_walk($item, 'get_strings', $old_key . $key . ".");
    } else {
        $results[$old_key . $key] = $item;
    }
}

array_walk($h, 'get_strings');

print_r($results); //returns Array ( [app.level1.level2.level3] => 3 [app.level1.level4.level5] => 2 )

array_walk() documentation: http://php.net/manual/en/function.array-walk.php

1 Comment

This works. Thank you! I've made some changes to it in order to keep everything in a single function. I'll be posting it as an answer just in case others wish to see it.
0

Although I must give credit to @kennypu, I've made some slight modifications to the answer in order to contain the code in one function without the use of global or any other variables within the class (keeping it all in one method).

public static function buildString($array, $delimeter = '.') {
    $results = array();
    $func = function($item, $key, $old_key = NULL) use (&$func, &$results, $delimeter) {
        if(is_array($item)) {
            array_walk($item, $func, $old_key . $key . $delimeter);
        } else {
            $results[$old_key . $key] = $item;
        }
    };
    array_walk($array, $func);
    return  $results;
}

In essence I created an anonymous function that uses parameters from the parent with the use of the key word use. Although not much documentation can be found for use some examples are shown here: Anonymous Functions.

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.