Aflext
Aflext

Reputation: 309

how to merge dimensional arrays

var list1 = [
    {
        id: 'node1',
        children: [
            {
                id: 'node11',
                children: []
            }
        ]
    }
];

var list2 = [
    {
        id: 'node1',
        children: [
            {
                id: 'node13',
                children: []
            }
        ]
    }
];
var resultList = [
    {
        id: 'node1',
        children: [
            {
                id: 'node11',
                children: []
            }, {
                id: 'node13',
                children: []
            }
        ]
    }
];

All my arrays are trees,one node can only belong to one parent. I want to merge list1 with list2 and get the resultList.I tried many ways, recursive callback,string search & replace and so on, but i still couldn't figure it out.

Upvotes: 6

Views: 117

Answers (2)

TimoStaudinger
TimoStaudinger

Reputation: 42460

The following code will merge all levels of the two tree arrays, not just on the upper most level:

var list1 = ...
var list2 = ...

var addNode = function(nodeId, array) {
  array.push({id: nodeId, children: []});
};

var placeNodeInTree = function(nodeId, parent, treeList) {
  return treeList.some(function(currentNode){

    // If currentNode has the same id as the node we want to insert, good! Required for root nodes.
    if(currentNode.id === nodeId) {
      return true;  
    }

    // Is currentNode the parent of the node we want to insert?
    if(currentNode.id === parent) {

      // If the element does not exist as child of currentNode, create it
      if(!currentNode.children.some(function(currentChild) {
        return currentChild.id === nodeId;
      })) addNode(nodeId, currentNode.children);

      return true;
    } else {

      // Continue looking further down the tree
      return placeNodeInTree(nodeId, parent, currentNode.children);
    }
  });
};

var mergeInto = function(tree, mergeTarget, parentId) {
  parentId = parentId || undefined;
  tree.forEach(function(node) {

    // If parent has not been found, placeNodeInTree() returns false --> insert as root element
    if(!placeNodeInTree(node.id, parentId, mergeTarget)){
      list1.push({id: node.id, children:[]});
    }

    mergeInto(node.children, mergeTarget, node.id);

  });
};

mergeInto(list2, list1);

document.write('<pre>');
document.write(JSON.stringify(list1, null, 4));
document.write('</pre>');

See the code live on JSBin: http://jsbin.com/wikaricita/3/edit?js,output

Note that it this algorithm has a complexity of O(n^2), which means that it will not scale really well. If the trees get very big or performance is a critical issue, you probably want to look into other ways of solving this problem.

Upvotes: 0

user3589620
user3589620

Reputation:

If I understand you correctly, you want it compact by id.

function getCompactById(arr) { // must have the same id
    var res = [];
    var obj = {};
    obj.id = arr[0][0].id;
    obj.children = [];
    for(var i = 0; i < arr.length; i += 1) {
        obj.children.push(arr[i][0].children[0]);
    }
    res.push(obj);
    return res;
}

The array looks like var arr = [list1, list2]; In the function create an array and an object. The object gets an id and an array. The id is always the same, so we take it from the first array. Go through the array and push all objects arr[i][0].children[0]. After the loop push the obj in the array. Return the result array.

Demo

Upvotes: 2

Related Questions