17

I have an array of strings that describe the parent/child relationship by being delimited with dashes. So, if Bob's boss was Jim and Jim's boss was Fred, Bob's entry in the array would be "Fred-Jim-Bob" and Jim's entry would be "Fred-Jim." I don't have the ability to change the way the data is coming in so I was looking for help as far as the best way of turning these values into JSON similar to this:

{
    "name": "Fred",
    "children": {
        "name": "Jim",
        "children": {
            "name": "Bob"
        }
    }
}

Any help would be greatly appreciated. Thanks.

Munzilla
  • 3,595
  • 5
  • 26
  • 35
  • can you give an example of the input string? also, does it go down infinite levels, or is it limited to 3? – Jason Jun 03 '11 at 21:21
  • Well it would be an array of strings like the ones shown above. So for the json I mentioned above the array might be: var emp = new Array("Fred-Jim","Fred","Fred-Jim-Bob"); and yes it could be more or less than 3. – Munzilla Jun 03 '11 at 21:28

1 Answers1

35
var input = ["Fred-Jim-Bob", "Fred-Jim", "Fred-Thomas-Rob", "Fred"];
var output = [];
for (var i = 0; i < input.length; i++) {
    var chain = input[i].split("-");
    var currentNode = output;
    for (var j = 0; j < chain.length; j++) {
        var wantedNode = chain[j];
        var lastNode = currentNode;
        for (var k = 0; k < currentNode.length; k++) {
            if (currentNode[k].name == wantedNode) {
                currentNode = currentNode[k].children;
                break;
            }
        }
        // If we couldn't find an item in this list of children
        // that has the right name, create one:
        if (lastNode == currentNode) {
            var newNode = currentNode[k] = {name: wantedNode, children: []};
            currentNode = newNode.children;
        }
    }
}

output JSONifies as:

[{
    "name": "Fred",
    "children": [{
        "name": "Jim",
        "children": [{
            "name": "Bob",
            "children": []
        }]
    }, {
        "name": "Thomas",
        "children": [{
            "name": "Rob",
            "children": []
        }]
    }]
}]
Gijs
  • 5,023
  • 1
  • 24
  • 42
  • 1
    The example input happens to have strings that go up to 3 levels, but you're welcome to add more. Try loading the example and making one of the strings say `"Fred-Jim-Bob-Mark"`. You'll see it works fine, too. Mathematical infinity it probably won't handle, but anything within reasonable bounds when browser memory is concerned should work. – Gijs Jun 03 '11 at 21:54
  • Yes, I'm using this to parse out data for a company's org chart, so I don't need INFINITE levels, but prepared for more than 3. – Munzilla Jun 06 '11 at 13:33
  • 2
    Works great, is there anyway you can add comments this code? I'm getting lost when debugging where you're setting currentNode = currentNode[k] = currentNode[k].children or currentNode = newNode.children which I believe is one of the most important steps in this algorithm. – LeLong37 Jul 16 '14 at 15:11