0

I have the following script that will loop over a huge JSON array to gather some information:

function recursiveTree(data, p_dim_name, p_dim_label, p_field_name, p_field_label) {
    var outputArray = [];
    for (parent_key in data) {
      if(data[parent_key]["name"]!="meta" && data[parent_key]["type"]!="start" && data[parent_key]["type"]!="end" && data[parent_key]["type"]!="deviceid" && data[parent_key]["type"]!="today"){
        var dim_name = "";
        var dim_label = "";
        var field_name = "";
        var field_label = "";
        var field_type = "";
        dim_name = p_dim_name == "" ? data[parent_key]["name"] : p_dim_name;
        field_name = p_field_name == "" ? data[parent_key]["name"] : p_field_name+"/"+data[parent_key]["name"];
        field_type = data[parent_key]["type"] == undefined ? "select multiple" : data[parent_key]["type"];

        if (data[parent_key]["label"] && typeof data[parent_key]["label"] === "object") {
          dim_label = p_dim_label == "" ? data[parent_key]["label"]["english"] : p_dim_label+"/"+data[parent_key]["label"]["english"];
          field_label =  data[parent_key]["label"]["english"];
        } else if (data[parent_key]["label"] && typeof data[parent_key]["label"] != "object") {
          dim_label = p_dim_label == "" ? data[parent_key]["label"] : data[parent_key]["label"]+"/"+p_dim_label;
          field_label = data[parent_key]["label"] ;
        }
        else  {
          dim_label = dim_name;
        }
        // field_label = p_field_label == "" ? data[parent_key]["label"] : data[parent_key]["label"]+"/"+p_dim_label+"/"+dim_label;
        //console.log(("children" in data[parent_key]))
        if (data[parent_key].children && data[parent_key].type != "select one") {
          recursiveTree(data[parent_key]["children"], dim_name, dim_label, field_name, field_label);
        }
        else {
            var obj = {};
            obj = 
            {
                "dim_label": dim_label,
                "dim_name": field_name.slice(0, field_name.lastIndexOf("/")),
                "field_name": field_name,
                "field_label": field_label,
                "field_type": field_type
            };
        }
        outputArray.push(obj)
        
      }
      
    }
    console.log(outputArray)
  }

And here is a small snippet of the JSON array I have:

var data = {
    "name": "Info",
    "title": "Info",
    "default_language": "default",
    "id_string": "...",
    "type": "survey",
    "children": [
        {
            "type": "text",
            "name": "basic_info",
            "label": "Basic Info",
            "children": [
                {
                    "type": "text",
                    "name": "name",
                    "label": {
                        "english": "What is your name"
                    }
                },
                {
                    "type": "text",
                    "name": "address",
                    "label": {
                        "english": "What is your address?"
                    }
                }
            ]
        },
        {
            "type": "text",
            "name": "more_data",
            "label": "More Data",
            "children": [
                {
                    "type": "text",
                    "name": "favourite_food",
                    "label": {
                        "english": "What is your favourite food?"
                    }
                },
                {
                    "type": "text",
                    "name": "favourite_destination",
                    "label": {
                        "english": "What is your favourite destination?"
                    },
                    "children": [
                        {
                            "type": "text",
                            "name": "france",
                            "label": {
                                "english": "France"
                            }
                        },
                        {
                            "type": "text",
                            "name": "usa",
                            "label": {
                                "english": "USA"
                            }
                        }
                    ]
                }
            ]
        },
        {
            "type": "number",
            "name": "estimated_income",
            "label": "What is your annual estimated income?"
        }
    ]
}

The problem is when I push into the output array, I cannot get the end result in one single array, but in multiple ones. Check this jsfiddle.

I need the final objects to be in one single array. The script is doing great using recursive approach, but the push into the array is returning multiple arrays.

Here is an image when I run the script over my original array:

enter image description here

alim1990
  • 4,656
  • 12
  • 67
  • 130
  • Again, I think [my answer](https://stackoverflow.com/a/66050740/1243641) to your previous question on this same topic has much simpler code. – Scott Sauyet Feb 05 '21 at 15:00

2 Answers2

2

it return single result but you call console.log(outputArray) multiple times, change it to return outputArray

this call has no variable assigned, did you mean var obj = recursiveTree(...)

if (data[parent_key].children && data[parent_key].type != "select one") {
    recursiveTree(data[parent_key]["children"], dim_name, dim_label, field_name, field_label);
}
uingtea
  • 6,002
  • 2
  • 26
  • 40
0

Here is the answer. I moved the outputArray declaration into outside of the function and returned back at the end of the method:

var data = {name: "Info", title: "Info", default_language: "default", id_string: "...", type: "survey", children: [{type: "text", name: "basic_info", label: "Basic Info", children: [{type: "text", name: "name", label: {english: "What is your name"}}, {type: "text", name: "address", label: {english: "What is your address?"}}]}, {type: "text", name: "more_data", label: "More Data", children: [{type: "text", name: "favourite_food", label: {english: "What is your favourite food?"}}, {type: "text", name: "favourite_destination", label: {english: "What is your favourite destination?"}, children: [{type: "text", name: "france", label: {english: "France"}}, {type: "text", name: "usa", label: {english: "USA"}}]}]}, {type: "number", name: "estimated_income", label: "What is your annual estimated income?"}]}

var outputArray = [];
function recursiveTree(data, p_dim_name, p_dim_label, p_field_name, p_field_label) {
for (parent_key in data) {
    if(data[parent_key]["name"]!="meta" && data[parent_key]["type"]!="start" && data[parent_key]["type"]!="end" && data[parent_key]["type"]!="deviceid" && data[parent_key]["type"]!="today"){
    var dim_name = "";
    var dim_label = "";
    var field_name = "";
    var field_label = "";
    var field_type = "";
    dim_name = p_dim_name == "" ? data[parent_key]["name"] : p_dim_name;
    field_name = p_field_name == "" ? data[parent_key]["name"] : p_field_name+"/"+data[parent_key]["name"];
    field_type = data[parent_key]["type"] == undefined ? "select multiple" : data[parent_key]["type"];

    if (data[parent_key]["label"] && typeof data[parent_key]["label"] === "object") {
        dim_label = p_dim_label == "" ? data[parent_key]["label"]["english"] : p_dim_label+"/"+data[parent_key]["label"]["english"];
        field_label =  data[parent_key]["label"]["english"];
    } else if (data[parent_key]["label"] && typeof data[parent_key]["label"] != "object") {
        dim_label = p_dim_label == "" ? data[parent_key]["label"] : data[parent_key]["label"]+"/"+p_dim_label;
        field_label = data[parent_key]["label"] ;
    }
    else  {
        dim_label = dim_name;
    }
    var obj = {};
        obj = 
        {
            "dim_label": dim_label,
            "dim_name": field_name.slice(0, field_name.lastIndexOf("/")),
            "field_name": field_name,
            "field_label": field_label,
            "field_type": field_type
        };
    // field_label = p_field_label == "" ? data[parent_key]["label"] : data[parent_key]["label"]+"/"+p_dim_label+"/"+dim_label;
    //console.log(("children" in data[parent_key]))
    if (data[parent_key].children && data[parent_key].type != "select one") {
        recursiveTree(data[parent_key]["children"], dim_name, dim_label, field_name, field_label);
    }
    outputArray.push(obj)

    }

}
return outputArray;
}

var result = recursiveTree(data["children"], "", "", "", "");
console.log(result)
.as-console-wrapper {max-height: 100% !important; top: 0}
Scott Sauyet
  • 49,207
  • 4
  • 49
  • 103
alim1990
  • 4,656
  • 12
  • 67
  • 130
  • I would suggest that global variables are a code smell. You can definitely do this recursively without that. – Scott Sauyet Feb 05 '21 at 15:01
  • What do you mean? – alim1990 Feb 05 '21 at 17:09
  • In your fix `outputArray` is moved to the global scope. It's not a local variable of some function or some block, but can be changed by any part of the program at any time. This can lead to [all sorts of problems](http://wiki.c2.com/?GlobalVariablesAreBad). – Scott Sauyet Feb 05 '21 at 17:27
  • But if i set it inside the function it will be initialized to empty each time the recursive part takes effect. – alim1990 Feb 06 '21 at 09:26
  • Right. You'd have to solve for that. Look around at some other JS recursion questions to see techniques for that. – Scott Sauyet Feb 06 '21 at 14:07
  • 1
    I can send the value of the current array with the recursive part. – alim1990 Feb 07 '21 at 17:34