将字符串树转换为数组

时间:2019-06-03 14:47:04

标签: javascript ecmascript-6

我有一个ID为字符串的对象。每个对象可以是另一个对象的子代。可以从ID猜测关系。例如:

[
  { id: '1:2:6', ids: ['1', '2', '6'] },
  { id: '1:4', ids: ['1', '4'] },
  { id: '1', ids: ['1'] },
  { id: '1:2', ids: ['1', '2'] },
]

在此示例中,根对象是id: 1,它有2个孩子id: 1:2id: 1:4。最后,id: 1:2有一个孩子id: 1:2:6

我想将此数组转换为将孩子嵌入父母的另一个数组,因此前一个数组将导致:

[
  {
    id: '1',
    children: [
      {
        id: '1:2',
        children: [
          { id: '1:2:6', children: [] }
        ],
      },
      {
        id: '1:4',
        children: [],
      }
    ],
  }
]

我可以使用ES6。我花了几个小时尝试使用各种循环来找到解决方案,但我无法弄清楚。任何帮助将不胜感激!

4 个答案:

答案 0 :(得分:4)

您可以通过在实际级别上查找对象来迭代对象并减少ids。如果找不到,请创建一个新对象。然后返回孩子们。

var data = [{ id: '1:2:6', ids: ['1', '2', '6'] }, { id: '1:4', ids: ['1', '4'] }, { id: '1', ids: ['1'] }, { id: '1:2', ids: ['1', '2'] }],
    tree = data.reduce((r, { ids }) => {
        ids.reduce((t, _, i, a) => {
            var id = a.slice(0, i + 1).join(':'),
                temp = t.find(o => o.id === id);
            
            if (!temp) t.push(temp = { id, children: [] });
            return temp.children;
        }, r);
        return r;
    }, []);

console.log(tree);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 1 :(得分:2)

我认为迭代方法更具可读性,因此也许所提供的解决方案将帮助您了解其完成方式(尽管它受到Nina的回答的启发)

所以我们要做的是遍历列表中的所有对象。 最初,对于每个对象,我们将当前的nodeList设置为最终树。我们遍历id的长度。

首先,我们通过将ids数组分为slice(['1'],['1','2'], ['1','2','6')并用:连接到字符串。因此,我们为第一项获得1,1:2,1:2:6 ids。

接下来,我们通过先前构造的ID在currentNodelist中找到一个节点。如果找不到节点,则意味着我们尚未添加它,因此我们需要创建并添加它(如果找到它,则不需要添加它)。

下一步,我们需要更深入地研究树,以便将当前创建的节点(或找到的节点)的子节点分配为currentNodelist。这样,我们将通过提供的ID更深入地遍历树。

let objs = [
  { id: '1:2:6', ids: ['1', '2', '6'] },
  { id: '1:4', ids: ['1', '4'] },
  { id: '1', ids: ['1'] },
  { id: '1:2', ids: ['1', '2'] },
];

let tree = [];
for (let i = 0; i < objs.length; i++) {
  let obj = objs[i];

  let currentNodeList = tree;
  for (let j = 0; j < obj.ids.length; j++) {
    let id = obj.ids.slice(0, j + 1).join(':');
    let currentNode = currentNodeList.find((node) => node.id === id);

    if (!currentNode) {
      currentNode = {id, children: []};
      currentNodeList.push(currentNode);
    } 

    currentNodeList = currentNode.children;
  }
}

console.log(tree);

我创建了一个简单的gif,显示了前2个迭代中发生的情况。箭头指向currentListNode

enter image description here

答案 2 :(得分:0)

首先“在纸上”弄清楚算法。让我们从一棵空树开始,并获取第一个条目: [1,2,6]。

  1. 节点1:将1加到树上-它现在是根和最后访问的节点。
  2. 节点2:将子节点2添加到节点1。
  3. 节点6:将子节点6添加到节点2。

在处理下一个条目[1,4]时,树中已经有1个-只需在其中添加4个即可。

在处理最后一个条目[1,2]时,请注意树中也已经存在2。

P.S。是“孩子”而不是“孩子”。

答案 3 :(得分:0)

使用递归算法构建树

var jsonTree = [{ id: '1:2:6', ids: ['1', '2', '6'] },{ id: '1:4', ids: ['1', '4'] },{ id: '1', ids: ['1'] },{ id: '1:2', ids: ['1', '2'] },]

var newJsonTree = [];
var currentElement = {id: '1',childs: []}
newJsonTree.push(currentElement)

function buildTree(jsonTree, currentElement){
    for(var i=0;i<jsonTree.length;i++){
        var parent = jsonTree[i];
        for(var j=0;j<jsonTree.length;j++){
            var child = jsonTree[j];
            if(child['visited'] != true && child['id'] != currentElement['id'] && child['id'].indexOf(currentElement['id']) == 0 ){
                if(child['id'].split(":").length == currentElement['id'].split(":").length+1){
                    var newElement = {}
                    newElement['id'] = child['id'];
                    newElement['childs'] = [];
                    currentElement['childs'].push(newElement);
                    child['visited'] = true;
                    buildTree(jsonTree, newElement);
                }
            }
        }
    }
}

buildTree(jsonTree, currentElement);
document.write(JSON.stringify(newJsonTree));

结果:

[{“ id”:“ 1”,“ childs”:[{“ id”:“ 1:4”,“ childs”:[]},{“ id”:“ 1:2”,“ childs “:[{” id“:” 1:2:6“,” childs“:[]}]}]}}]