Geoff Clayton
Geoff Clayton

Reputation: 1183

PHP - replace array keys recursively and change values to array including old key

I've spent a while trying to get what I need from old answers but haven't quite got it (have got close though!).

I have this;

[January] => Array
    (
        [Tuesday] => Array
            (
                [foo] => Array
                    (
                        [82] => 47731
                        [125] => 19894
                    )

                [bar] => Array
                    (
                        [82] => 29911
                        [125] => 10686
                    )

            )

    }

...and I want this;

[0] => Array
    (
       'key' => 'January'
       'children' => Array
            [0] => Array 
                {
                    'key' => 'Tuesday'
                    'children' => Array 
                         [0] => Array 
                              {
                                  'key' => 'foo'
                                  'values' => Array
                                        {
                                             [82] => 47731
                                             [125] => 19894
                                        }
                         [1] => Array
                              {
                                  'key' => 'bar'
                                  'values' => Array
                                        {
                                             [82] => 29911
                                             [125] => 10686
                                        }
                              }
                )
    }

I've got fairly close by adapting the first answer from Recursively change keys in array but only the bottom layer of my result is correct - the nodes with keys 'Tuesday', 'foo' and 'bar' just look the same as in the source array.

Here's what I've got so far;

public function transform_hierarchical_output(&$var)
{       
    if (is_array($var)) 
    {
        $final = [];

        $i = 0;

        foreach ($var as $k => &$v) 
        {
            $new_node = [
                'key'       => $k,
                'children'  => $v
            ];

            $k = $i;

            $this->transform_hierarchical_output($v);

            $final[$k] = $new_node;

            $i++;
        }

        $var = $final;
    } 
    elseif (is_string($var)) 
    {

    }
}

This needs to work with a source array of any length and depth.

Thanks in advance.

Geoff

Upvotes: 3

Views: 1325

Answers (3)

Mostafa Talebi
Mostafa Talebi

Reputation: 9183

First thing I should note is that, though there are many recursions in your example, but technically it is not a recursive loop in terms of the need for a self-executing function. Because your loop's scheme fluctuates a bit in its depth, it does not follow a regular pattern down to is last node; however it is a logical scheme, but is not repeated down to is last node.

The following function might work for you:

function doArray($array)
{
    $keys = array_keys($array);
    $arr_count = count($keys);
    $new_array;

    for($i = 0; $i < $arr_count; $i++)
    {
        $new_array[$i]["key"] = $keys[$i];

        $new_keys = array_keys($array[$keys[$i]]);

        for($w = 0; $w < count($new_keys); $w++)
        {
            $new_array[$i]["children"][$w]["keys"] = $new_keys[$i];
            $new_array[$i]["children"][$w]["children"] = array();
            for($w = 0; $w < count($new_keys); $w++)
            {
                $new_new_keys = array_keys($array[$keys[$i]][$new_keys[$w]]);
                for($q = 0; $q < count($new_new_keys); $q++)
                {
                    $new_array[$i]["children"][$w]["children"][$q]["key"] = $new_new_keys[$q];
                    //$new_array[$i]["children"][$w]["children"][$q]["children"] = $array[$keys[$i]][$new_keys[$w]][$new_new_keys[$q]];

                    $last_new_keys = array_keys($array[$keys[$i]][$new_keys[$w]][$new_new_keys[$q]]);
                    for($s  = 0; $s < count($last_new_keys); $s++)
                    {
                        $new_array[$i]["children"][$w]["children"][$q]["values"][$last_new_keys[$s]] = $array[$keys[$i]][$new_keys[$w]][$new_new_keys[$q]][$last_new_keys[$s]];
                    }
                }

            }
        }

    }

    return $new_array;
}

Upvotes: 0

Chris Lam
Chris Lam

Reputation: 3614

<?php

$array = [
    'January' => [
        'Tuesday' => [
            'foo' => [
                82 => 47731,
                125 => 19894,
            ],

            'bar' => [
                82 => 47731,
                125 => 19894,
            ]
        ]
    ]
];

function transform(array $input)
{
    $output = [];

    foreach ($input as $key => $val) {
        if (is_array(array_values($val)[0])) { // if next depth is an array
            $output[] = [
                'key'       => $key,
                'children'  => transform($val)
            ];
        } else {
            $output[] = [
                'key'    => $key,
                'values' => $val
            ];
        }
    }

    return $output;
}

print_r(transform($array));

Upvotes: 3

Bo Chen
Bo Chen

Reputation: 436

try below:

function t($arr)
    {

        $a = [];

        $num = 0;
        foreach($arr as $k => $v) {
            if (is_array($v))
            {
                $a[$num] = [
                    'key' => $k,
                ];
                $a[$num][is_array(array_values($v)[0]) ? 'children' : 'values'] = t($v);
                $num ++;
            } else {
                $a[$k] = $v;
            }
        }
        return $a;
    }

Upvotes: 2

Related Questions