递归 - 将Javascript Map转换为嵌套的JSON对象

时间:2015-03-17 05:26:08

标签: javascript json recursion

提前感谢您的帮助!

我试图将特定的javascript地图转换为嵌套的JSON对象。地图样本如下:

["a", ["b", "c"]]
["b", ["e"]]
["c", ["f"]]
["e", []]
["f", []]

其中键表示父节点,并且数组中的值是其直接子节点。值的空数组表示该给定键没有子项。我想生成一个看起来像的输出:

{
    "name": “a”,
    "children": [{
        "name": “b”,
        "children": [{
            "name": “e”
            }]
        }, {
            "name": “c”,
            "children": [{
                "name": “f”,
            }]
        }]
}

(这可能不是一个格式正确的json对象,但希望是javascript示例地图演示的层次关系的说明)。另外,尽管是微不足道的,但假设键中的键和值都被排序。

最后,我知道这有助于递归解决方案。任何帮助都会非常感激。再次感谢您的时间!

2 个答案:

答案 0 :(得分:1)

您想要学习解决此问题的算法称为topological sorting,它假设您上面描述的图形没有周期,但对于上述情况,算法可以修改为一点点找不到没有父节点的节点作为根节点。

可能的解决方案:



var hasParent = {};

function computeParentCount(data) {
  stack = [];
  for (key in data) {
    data[key].forEach(function (child) {
      hasParent[child] = true;
    });
  }
}

function appendAfterDfs(res, data, key) {
  var node = {
    name: key
  };
  if (data[key].length) {
    // only nodes with a children array with more than 0 elements
    // have children in the json
    node.children = [];
  }
  data[key].forEach(function (child) {
    appendAfterDfs(node.children, data, child);
  });
  res.push(node);
}

function main() {

  var data = {
    'a': ['b', 'c'],
    'b': ['e'],
    'c': ['f'],
    'e': [],
    'f': [],
  };

  computeParentCount(data);

  // build the json
  var res = [];
  for (key in data) {
    if (!hasParent[key]) {
      appendAfterDfs(res, data, key);
    }
  }
  document.write('<pre>' + JSON.stringify(res, null, '  ') + '</pre>');
}

main()
&#13;
&#13;
&#13;

说明:

  1. 首先找到没有父级的密钥(并称之为root个节点)
  2. 每个根节点通过data对象执行dfs,直到节点没有任何子节点
  3. 收集流程中的每个节点(将其保存在父级子节点中)

答案 1 :(得分:0)

如果我们可以假设列表中的第一项是“顶部”项目,并且没有循环或类似的东西,那么有一个相当简单的解决方案:

function buildTree(items) {
  // build map of node name -> node
  var map = items.reduce(function(l, n) {
    l[n[0]] = { name: n[0] };
    return l;
  }, {});

  // assign children
  items.filter(function(it) { return it[1].length; })
  .forEach(function(it) {
    map[it[0]].children = it[1].map(function(key) {
      return map[key];
    });
  });

  // return the node for the first item in `items`
  return map[items[0][0]];
}

var tree = buildTree([
  ["a", ["b", "c"]],
  ["b", ["e"]],
  ["c", ["f"]],
  ["e", []],
  ["f", []]
]);

console.log(tree);