skip to Main Content

For four days I am trying to figure out how to solve this, as well as googling it, and was no luck

The problem is that I needed to loop through a nested array (for unknown deep) and keep the top-level keys (as a prefix to the last value) as long as I am still going deep, and then start over (the prefix need to reset) once it started a new path.

I want to generate complete addresses from this array.

$arr = [
    "buildings" => [
        "group1" => [
            "b1" => [1,2,3,4],
            "b2" => [1,2,3]
        ],
        "group2" => [
            "b1" => [1,2]
        ]
    ],
    "villas" =>[
        "group1" => [
            "v1" => [1,2],
            "v2" => [1]
        ],
        "group2" => [
            "v1" => [1],
            "v2" => [1]
        ],
        "group3" => [
            "v1" => [1]
        ],
    ]
];

This is the needed output

buildings/group1/b1/1
buildings/group1/b1/2
buildings/group1/b1/3
buildings/group1/b1/4
buildings/group1/b2/1
buildings/group1/b2/2
buildings/group1/b2/3
buildings/group2/b1/1
buildings/group2/b1/2
villas/group1/v1/1
villas/group1/v1/2
villas/group1/v2/1
villas/group2/v1/1
villas/group2/v2/1
villas/group3/v1/1

I tried this function but also it didn’t bring the wanted results

function test($array, $path = ""){
    foreach ($array as $key => $value) {
        if (is_array($value)){
            $path .= $key."/";
            test($value, $path);
        } else {
            echo $path.$value."<br>";
        }
    }
}
test($arr);

UPDATE

I understood where was my mistake and I wanted to share with you my modification to my method after I fixed it.

function test($array, $path = ""){
    foreach ($array as $key => $value) {
        if (is_array($value)){
            test($value, $path . $key . '/');
        } else {
            echo $path.$value."<br>";
        }
    }
}

And thanks to @Kai Steinke he’s method is way better than mine, and here is some improvements just to make it look better.

function flatten(array $array, array $flattened = [], string $prefix = ''): array
{
    foreach ($array as $key => $value) {
        if (is_array($value)) {
            $flattened = array_merge( flatten($value, $flattened, $prefix . $key . '/'));
            continue;
        }
        $flattened[] = $prefix . $value;
    }
    return $flattened;
}

2

Answers


  1. Here you go:

    function flatten($arr, $prefix = '') {
        $result = [];
        foreach ($arr as $key => $value) {
            if (is_array($value)) {
                $result = array_merge($result, flatten($value, $prefix . $key . '/'));
            } else {
                $result[] = $prefix . $value;
            }
        }
        return $result;
    }
    
    // Usage
    print_r(flatten($arr))
    

    Returns an Array:

    Array ( 
        [0] => buildings/group1/b1/1 
        [1] => buildings/group1/b1/2 
        [2] => buildings/group1/b1/3 
        [3] => buildings/group1/b1/4 
        [4] => buildings/group1/b2/1 
        [5] => buildings/group1/b2/2 
        [6] => buildings/group1/b2/3 
        [7] => buildings/group2/b1/1 
        [8] => buildings/group2/b1/2 
        [9] => villas/group1/v1/1 
        [10] => villas/group1/v1/2 
        [11] => villas/group1/v2/1 
        [12] => villas/group2/v1/1 
        [13] => villas/group2/v2/1 
        [14] => villas/group3/v1/1 
    )
    
    Login or Signup to reply.
  2. Build and preserve the path using all encountered keys until arriving at a deep non-array value, then append the value to the string, and push the full path into the result array.

    Code: (Demo)

    function flatten(array $array, string $path = ''): array
    {
        $result = [];
        foreach ($array as $k => $v) {
            array_push(
                $result,
                ...(is_array($v) ? flatten($v, "$path$k/") : ["$path$v"])
            );
        }
        return $result;
    }
    
    var_export(flatten($array));
    

    A slightly related answer where a slash-delimited string was built as the hierarchical path to a search value.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search