0

I created a PHP function that will convert an array:

[
    'one/two' => 3,
    'one/four/0' => 5,
    'one/four/1' => 6,
    'one/four/2' => 7,
    'eight/nine/ten' => 11,
]

Into the following JSON string:

{
    "one":
    {
        "two": 3,
        "four": [ 5,6,7]
    },
    "eight":
    {
        "nine":
        {
            "ten":11
        }
    }
}

Here is the function:

<?php
function toJsonStr($array) {

    $final_array = [];

    foreach ($array as $key => $value) {

        $key_exploded = explode("/", $key);

        $array_index_at_end = is_numeric(end($key_exploded)) ? true : false ;

        if ($array_index_at_end === true) {
            $array_index = array_pop($key_exploded);
        }

        $ref = &$final_array;
        foreach ($key_exploded as $value2) {

            if (!isset($ref[$value2])) {
                $ref[$value2] = [];
            }

            $ref = &$ref[$value2];
        }

        if ($array_index_at_end === true) {
            $ref[$array_index]=$value;
        } else {
            $ref=$value;
        }
    }

    return json_encode($final_array);
}


$array = [
    'one/two' => 3,
    'one/four/0' => 5,
    'one/four/1' => 6,
    'one/four/2' => 7,
    'eight/nine/ten' => 11,
];

$json_str = toJsonStr($array);

echo "\n";
print_r($json_str);
echo "\n\n";

I'm almost positive that this can also be done recursively. I am new to recursion and am having trouble structuring an approach when creating a recursive version.

Would it even be worthwhile to create a recursive version? Maybe it would be too difficult to understand compared to the simple foreach within a foreach I have implemented above?

I know that recursive algorithms simplify and make code more compact but in this case would it be worth it?

  • 1
    have a read of https://stackoverflow.com/questions/5250733/what-are-the-advantages-and-disadvantages-of-recursion. Some interesting responses here which may be of use – Juakali92 Mar 19 '18 at 15:32
  • 1)For the most part recursion is slower, and takes up more of the stack as well. The main advantage of recursion is that for problems like tree traversal it make the algorithm a little easier or more "elegant". 2) Expressiveness Most problems are naturally expressed by recursion such as Fibonacci, Merge sorting and quick sorting. In this respect, the code is written for humans, not machines. Considering the above points, maybe a recursive version is not good in this situation. I'm thinking I should just keep the foreach that I have. – ponytails_soda Mar 19 '18 at 15:38

2 Answers2

1

IMHO a recursive approach would make sense if the structure of your input array can have a nested structure:

[
'one/two' => 3,
'one/four/0' => 5,
'one/four/1' => 6,
'one/four/2' => 7,
'eight/nine/ten' => 11,
'eleven/twelve' => [
  'thirteen/fourteen' => 15,
  'sixteen/seventeen' => 18,
  'nineteen/twenty' => [
    'twentyone/twentytwo' => 23
    ],
  ],
]

Then you should implement a recursive function for that. Keep it simple when you don't need to implement things.

Uwe Trotzek
  • 150
  • 9
  • Yes, this makes sense as I solved a problem recently with the help of stack citizens that used recursion. That situation had an unknown number of nested objects within objects (similar to the situation you are describing above). Recursion allowed that algorithm to be more compact and digestable. In THIS specific case since there is no nested structure, I shall follow your advice and keep it simple. Making things complicated just for the sake of it is not wise. – ponytails_soda Mar 19 '18 at 15:50
1

It can be shorter, though I usually do this without recursion, as it doesn't matter the depth. You already have a grasp of doing it with references. See How to access and manipulate multi-dimensional array by key names / path?:

function toJsonStr($array, &$result=array()) {
    foreach($array as $key => $value) {
        $path = explode('/', $key);
        $temp =& $result;    
        foreach($path as $key) {
            $temp =& $temp[$key];
        }
        $temp = $value;
    }
    $result = json_encode($result);
}

toJsonStr($array, $result);
AbraCadaver
  • 78,200
  • 7
  • 66
  • 87
  • Yeah, this is better--going with this. T.Y. – ponytails_soda Mar 19 '18 at 16:33
  • Originally I built it adding objects (stdClass) within objects but JSON treats PHP associative array like same Object key:value when encoded so switched to array. That would explain the !isset() being left in. – ponytails_soda Mar 19 '18 at 16:40
  • What is the significance of the pass by reference "&" having no space in the function parameter list and having a single space between variable in variable assignment in the function body? – ponytails_soda Mar 20 '18 at 17:38
  • 1
    @ponytails_soda: No significance, it can be `$temp = &$result;`. I got used to doing it the other way somewhere for some reason. – AbraCadaver Mar 21 '18 at 01:11
  • ty. I've seen people do that all the time and was wondering if it was some accepted best practice. – ponytails_soda Mar 21 '18 at 02:54