2

Given the following multidimensional array:

$menu = [
    'root' => [
        'items' => [
            'A' => [
                'p' => [1, 2, 9],
            ],
            'B' => [
                'p' => [1, 2, 3, 9],
            ],
            'C' => [
                'p' => [1, 2, 4, 9],
            ],
            'D' => [
                'items' => [
                    'D1' => [
                        'p' => [1, 2, 3, 4, 9],
                    ],
                    'D2' => [
                        'p' => [1, 2, 3, 4],
                    ],
                ],
            ],
            'E' => [
                'items' => [
                    'E1' => [
                        'p' => [1, 2, 10],
                    ],
                ],
            ],
            'F' => [
                'items' => [
                    'F1' => [
                        'p' => [5, 6],
                    ],
                    'F2' => [
                        'p' => [7, 8],
                    ],
                ],
            ],
        ],
    ],
];

Is there a way to get all the values in the 'p's as array, uniquely? The output should be [1, 2, 9, 3, 4, 10, 5, 6, 7, 8]

I tried a simple one-liner, but it works only for the first level (A, B, C), nested $items are ignored:

$ps = array_unique(call_user_func_array('array_merge', array_column($menu['root']['items'], 'p')));
print_r($ps);

I also tried to write a recursive function, but I get totally stuck and the output is not what's expected

function recursive_ps($elem, $arr = []){
    $output = $arr;
    if (isset($elem['items'])){
        foreach($elem['items'] as $key => $value){
            if (isset($value['p'])){
                $output = array_merge($arr, $value['p']);
                if (isset($value['items'])){
                    return recursive_ps($value, $output);
                }
            }
        }
    }
    return $output;
}
$o = recursive_ps($menu['root']);
print_r($o);

Please, any help?

1
  • What is the output you do get? Commented Apr 1, 2021 at 17:08

1 Answer 1

3

The main issue is to return recursive_ps in the loop. You have to merge the returned data with the current array.

The second if to test $values['items'] shouldn't be inside the $value[p].

Also, $output = array_merge($arr, $value['p']); should be $output = array_merge($output, $value['p']); to combine to the current array.

Working code: (demo)

function recursive_ps($elem) 
{
    if (!isset($elem['items'])) {
        return [];
    }
    $output = [];
    foreach($elem['items'] as $key => $value) {
        if (isset($value['p'])) {
            $output = array_merge($output, $value['p']);
        }
        if (isset($value['items'])) {
            // merge the return value of function
            $output = array_merge($output, recursive_ps($value));
        }
    }
    return $output;
}

$output = array_values(array_unique(recursive_ps($menu['root'])));
print_r($output);

Output:

Array
(
    [0] => 1
    [1] => 2
    [2] => 9
    [3] => 3
    [4] => 4
    [5] => 10
    [6] => 5
    [7] => 6
    [8] => 7
    [9] => 8
)

Another version using reference :

function recursive_ps($elem, &$arr = []) {
    if (isset($elem['items'])) {
        foreach($elem['items'] as $key => $value) {
            if (isset($value['p'])) {
                $arr = array_merge($arr, $value['p']);
            }
            if (isset($value['items'])) {
                recursive_ps($value, $arr); // pass array by reference
            }
        }
    }
}

$output = [];
recursive_ps($menu['root'], $output); // pass array by reference
print_r(array_values(array_unique($output)));
Sign up to request clarification or add additional context in comments.

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.