gameFrenzy07
gameFrenzy07

Reputation: 397

Recursion not returning right result

I am working on a problem where I would like to transform the following object structure:

[
    {
        "label": "testType",
        "categories": [
            {
                "label": "testCatType",
                "subCategories": [
                    {
                        "label": "newSubCat",
                        "subSubCategories": [
                            {
                                "label": "newSubSubCat1"
                            },
                            {
                                "label": "newSubSubCat2"
                            },
                            {
                                "label": "newSubSubCat3"
                            }
                        ]
                    }
                ]
            }
        ]
    },
    {
        "label": "newType",
        "categories": [
            {
                "label": "newCat10",
                "subCategories": [
                    {
                        "label": "newCatSub1",
                        "subSubCategories": [
                            {
                                "label": "bingo11"
                            },
                            {
                                "label": "bingo12"
                            },
                            {
                                "label": "bingo15"
                            }
                        ]
                    }
                ]
            }
        ]
    },
    {
        "label": "displacement",
        "categories": []
    },
    {
        "label": "brush",
        "categories": [
            {
                "label": "blood",
                "subCategories": []
            },
            {
                "label": "damage",
                "subCategories": []
            },
        ]
    }
]

into something like this:

{
    "testType": {
        "testCatType": {
            "newSubCat": {
                "newSubSubCat1": {},
                "newSubSubCat2": {},
                "newSubSubCat3": {}
            }
        }
    },
    "newType": {
        "newCat10": {
            "newCatSub1": {
                "bingo11": {},
                "bingo12": {},
                "bingo15": {}
            }
        }
    },
    "displacement": {},
    ....
}

I have implemented the following recursive solution for this:

recursiveAssign(obj, json) {
    if (_.isUndefined(obj)) {
      return;
    }

    let totalKeys = _.keys(obj);
    return _.assign(json, { [obj['label']]: this.test(obj[totalKeys[1]], json) })
  }

transform(typeObj){
    let json = {};
    _.forEach(typeObj, obj => {
      let totalKeys = _.keys(obj);
      if (totalKeys < 2) {
        _.assign(json, obj['label']);
      } else {
        _.assign(json, { [obj['label']]: this.recursiveAssign(obj[totalKeys[1]], json) })
      }
    })
}

Now the end result of this is an object that is a copy of itself on each level and I don't quite understand what the problem is. I think my approach is not faulty as I take the label and call the recursive function on the other part of that object. Can please someone point out to the potential issue!

Upvotes: 1

Views: 94

Answers (2)

Mulan
Mulan

Reputation: 135197

You can write transform as a simple recursive function -

function transform (all = []) {
  return Object.fromEntries(all.map(t =>
    [t.label, transform(t.categories ?? t.subCategories ?? t.subSubCategories)]
  ))
}

const data =
  [{"label":"testType","categories":[{"label":"testCatType","subCategories":[{"label":"newSubCat","subSubCategories":[{"label":"newSubSubCat1"},{"label":"newSubSubCat2"},{"label":"newSubSubCat3"}]}]}]},{"label":"newType","categories":[{"label":"newCat10","subCategories":[{"label":"newCatSub1","subSubCategories":[{"label":"bingo11"},{"label":"bingo12"},{"label":"bingo15"}]}]}]},{"label":"displacement","categories":[]},{"label":"brush","categories":[{"label":"blood","subCategories":[]},{"label":"damage","subCategories":[]},]}]

console.log(JSON.stringify(transform(data), null, 2))

{
  "testType": {
    "testCatType": {
      "newSubCat": {
        "newSubSubCat1": {},
        "newSubSubCat2": {},
        "newSubSubCat3": {}
      }
    }
  },
  "newType": {
    "newCat10": {
      "newCatSub1": {
        "bingo11": {},
        "bingo12": {},
        "bingo15": {}
      }
    }
  },
  "displacement": {},
  "brush": {
    "blood": {},
    "damage": {}
  }
}

You can chain ... ?? t.subSubSubCategories and ... ?? t.subSubSubSubCategories, if needed. A better approach would be to create a consistent node interface for all nodes in your graph. You could achieve this by renaming all sub*Categories to simply categories. This will give each node an inteface like

Node: { label: String, categories: Array<Node> }

Upvotes: 3

Harsh Saini
Harsh Saini

Reputation: 626

You can solve this in pure js like this:

const arr = [{ "label": "testType", "categories": [{ "label": "testCatType", "subCategories": [{ "label": "newSubCat", "subSubCategories": [{ "label": "newSubSubCat1" }, { "label": "newSubSubCat2" }, { "label": "newSubSubCat3" }] }] }] }, { "label": "newType", "categories": [{ "label": "newCat10", "subCategories": [{ "label": "newCatSub1", "subSubCategories": [{ "label": "bingo11" }, { "label": "bingo12" }, { "label": "bingo15" }] }] }] }, { "label": "displacement", "categories": [] }, { "label": "brush", "categories": [{ "label": "blood", "subCategories": [] }, { "label": "damage", "subCategories": [] }, ] }];

let result = recursive(arr);

console.log(result);

function recursive(arr) {
  let result = {};
  let returnValue = {}
  for (let obj of arr) {
    let entries = Object.entries(obj);
    if (!entries.length) {
      return {};
    }

    for (let [key, value] of entries) {
      if (typeof value == "object") {
        result = recursive(value);
      }
    }

    const label = obj["label"];
    returnValue = { ...returnValue,
      [obj["label"]]: result
    };
  }
  return returnValue;
}
.as-console-wrapper {min-height: 100%;}

Upvotes: 1

Related Questions