2
var array = [{"grandpa","father"}, {"father"}, {"grandpa","father","me"}];

Given the above array, I want to product a java-script object(JSON) like below, that has the parent-child like structure.

{"id":"grandpa",
 "children":[
    {"id":"father",
     "children":[
        {"id":"me",
         "children":[]
        }]
    }]
}
8
  • Produce the javascript object based on the array Commented Feb 18, 2010 at 3:12
  • If you can't enunciate the problem clearly, it's going to be hard for us to help you to solve it. Are you trying to decode JSON? Commented Feb 18, 2010 at 3:13
  • 1
    "[B]ased on the array": in what sense? How is the input related to the output? Commented Feb 18, 2010 at 3:17
  • The array is still invalid syntax. Commented Feb 18, 2010 at 3:26
  • Give a better description. Don't use so many of the same numbers, it makes it difficult for us to tell what is what. Try using non ambiguous words instead of numbers. Maybe even words that have natural hierarchy, like fruits => apples, oranges. Provide a valid javascript array. Commented Feb 18, 2010 at 3:26

3 Answers 3

8

If you're asking how you would take a list of hierarchy paths and create a tree structure, here's how you could do it in JavaScript:

function convertToHierarchy(arry /* array of array of strings */) 
{
    var item, path;

    // Discard duplicates and set up parent/child relationships
    var children = {};
    var hasParent = {};
    for (var i = 0; i < arry.length; i++) 
    {
        var path = arry[i];
        var parent = null;
        for (var j = 0; j < path.length; j++) 
        {
            var item = path[j];
            if (!children[item]) {
                children[item] = {};
            }
            if (parent) {
                children[parent][item] = true; /* dummy value */
                hasParent[item] = true;
            }
            parent = item;
        }
    }

    // Now build the hierarchy
    var result = [];
    for (item in children) {
        if (!hasParent[item]) {
            result.push(buildNodeRecursive(item, children));
        }
    }
    return result;
}

function buildNodeRecursive(item, children)
{
    var node = {id:item, children:[]};
    for (var child in children[item]) {
        node.children.push(buildNodeRecursive(child, children));
    }
    return node;
}

convertToHierarchy([["1","2"], ["1"], ["1","2","3"]]);

Edit:

Your question is still ambiguous. My previous version assumed these two things:

  1. Each node ID uniquely identifies a node
  2. A specified hierarchy path can start at other than the root node

In this sample, I'll assume the following:

  1. Node IDs are not unique, but they are unique within the children of a particular node
  2. All hierarchy paths start at the root node of the tree

Here's the code:

function convertToHierarchy(arry /* array of array of strings */)
{
    // Build the node structure
    var rootNode = {id:"root", children:{}}
    for (var i = 0; i < arry.length; i++)
    {
        var path = arry[i];
        buildNodeRecursive(rootNode, path, 0);
    }
    return rootNode;
}

function buildNodeRecursive(node, path, idx)
{
    if (idx < path.length)
    {
        item = path[idx];
        if (!node.children[item])
        {
            node.children[item] = {id:item, children:{}};
        }
        buildNodeRecursive(node.children[item], path, idx + 1);
    }
}

The hierarchy structure is returned, but the format's a bit different. However, you should get the picture.

Sign up to request clarification or add additional context in comments.

3 Comments

Yeah i'm looking for this. I tested, however convertToHierarchy returns empty children.
Oops, forgot that for..in doesn't work well for arrays. Verified it works with my edits.
Well, actually i need support for duplicates. Like, convertToHierarchy([["1","2"], ["1"], ["1","1","2"]]); Therefore we can't use the item as the key of the hash,
0

I think this should work. I'm using firebug to track the structure of the output.

    var el =  {"name": "Level 1", "paths" : ["fruits"]};
    var el2 = {"name": "Level 3", "paths" : ["fruits", "apples", "fuji"]};
    var el3 = {"name": "Level 4", "paths" : ["fruits", "apples", "fuji", "red"]};
    var el4 = {"name": "Level 2", "paths" : ["fruits", "apples"]};

    var allEl = [el, el2, el3, el4];


    /* Define recursive function for setting the child */
    function setChild(parent, pos, arr, name)
    {
        if(pos < arr.length)
        {
            if(pos == arr.length-1) //last element of the paths
                parent.name = name;

            if(!parent.children){
                parent.children = [];
                parent.children[0] = new Object();
            }
            setChild(parent.children[0], pos + 1, arr, name);
        }
    }

    /* Test starts here */
    var root = new Object();

    for(var i=0; i<allEl.length; i++)
    {
        var el = allEl[i];
        setChild(root, 0, el.paths, el.name);
    }

    //Firefox debugging ...getfirebug.com
    console.debug(root);

1 Comment

Hmm, doesn't work for nodes of the same level.. var arr = ["fruits"]; var arr2 = ["fruits", "apples", "fuji"]; var arr3 = ["fruits", "apples"]; var arr4 = ["fruits", "apples", "fuji", "red"]; var arr5 = ["fruits", "apples", "fuji", "green"];
-3

If you want to encode JSON, just use a JSON library.

Don't try and roll your own.

1 Comment

Read the question - he's not trying to encode JSON data, he's trying to build a tree from a flat data structure.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.