2

I've been trying to make a recursive function based on the help I got here: looping through an object (tree) recursively

I want to go through the object o and create a new one that is keyed on each key, and has a value of parents for everything above it.

My brain doesn't do recursive well, take a crack at it :-) .. if you want to try with the real data it is here

function eachRecursive(obj) {
    for (var k in obj) {
        if (typeof obj[k] == "object" && obj[k] !== null ) {
            eachRecursive(obj[k])
        }
        else {
            // do something to add to codes
        }
    }
}

var o = {
    "1": {
        name: "hi 1",
        children: {
            "1.1": {
                name: "hi 1.1",
                children: {
                    "1.1.1": {
                        name: "hi 1.1.1",
                        children: {}
                    }
                }
            },
            "1.2": {
                name: "hi 1.2",
                children: {}
            }
        }
    },
    "2": {
        name: "hi 2",
        children: {
            "2.1": {
                name: "hi 2.1",
                children: {}
            }
        }
    }
}

var codes = {}
eachRecursive(o)
console.log(codes)
// What I wish to have.
//{
//    "1": {
//        "name":"hi 1",
//        "parents":[]
//    },
//    "2": {
//        "name": "hi 2",
//        "parents": []
//    },
//    "1.1": {
//        "name": "hi 1.1",
//        "parents": ["1"]
//    },
//    "1.1.1": {
//        "name": "hi 1.1.1",
//        "parents": ["1", "1.1"]
//    },
//    "1.2": {
//        "name": "hi 1.2",
//        "parents": ["1"]
//    },
//    "2.1": {
//        "name": "hi 2.1",
//        "parents": ["2"]
//    }
//}
chimpsarehungry
  • 1,775
  • 2
  • 17
  • 28
  • You may want to use a map function and return the values for each item – Judson Terrell Aug 21 '17 at 22:39
  • will give this another go - the problem is the `parents` piece, that makes a recursive solution a little more annoying. If I don't get back to this - you might want to look into this library - https://github.com/paularmstrong/normalizr – Christopher Messer Aug 21 '17 at 22:57

2 Answers2

2

You could do it like this:

function eachRecursive(obj) {
    return (function recurse(result, obj, parents) {
        for (var key in obj || {}) {
            result[key] = { name: obj[key].name, parents: [...parents] };
            recurse(result, obj[key].children, parents.concat(key));
        }
        return result;
    })({}, obj, []);
}


var o = {
    "1": {
        name: "hi 1",
        children: {
            "1.1": {
                name: "hi 1.1",
                children: {
                    "1.1.1": {
                        name: "hi 1.1.1",
                        children: {}
                    }
                }
            },
            "1.2": {
                name: "hi 1.2",
                children: {}
            }
        }
    },
    "2": {
        name: "hi 2",
        children: {
            "2.1": {
                name: "hi 2.1",
                children: {}
            }
        }
    }
}

var codes = eachRecursive(o);
console.log(codes);
.as-console-wrapper { max-height: 100% !important; top: 0; }
trincot
  • 317,000
  • 35
  • 244
  • 286
2

You have to think step by step how you would do it by hand.

  1. if it is an object: add the actual node to the result, and after that call the function recursivly with the extended parents and the result.

  2. if it is not an object: just append it to the result.

I created a fiddle for you here: https://jsfiddle.net/11e8e4af/

function eachRecursive(obj) {
  var parents = arguments[1] || [];
  var result = arguments[2] || {};
  for (var k in obj) {
    if (obj.hasOwnProperty(k) && typeof obj[k] == "object" && obj[k] !== null ) {
      result[k] = {name:obj[k].name, parents:parents.slice()};
      eachRecursive(obj[k].children, parents.concat(k), result);
    } else {
      result[k] = {name:obj[k].name, parents:parents.slice()};
    }
  }
  return result;
}
Joshua K
  • 2,407
  • 1
  • 10
  • 13