JS如何改造这个不规则的对象

时间:2016-10-27 09:46:07

标签: javascript arrays

我有这个对象,它的键保证排序,并将用于操作。它的每个值都是一个二维数组。

var obj = {
  "0": [
    [0, 1], [0, 3], [0, 4]
  ],
  "1": [
    [1, 2], [1, 3]
  ],
  "2": [
    [2, 3], [2, 5]
  ],
  "3": [
    [3, 4], [3, 6]
  ],
  "5": [
    [5, 6]
  ],
  "6": [
    [6, 5]
  ]
}

我正在尝试连接它们,并且每个数组的最后一个值是该对象的下一个索引。所以,我的预期结果是这样的数组,

模式是,我必须找到从0这是obj的第一个索引到最后一个索引6的方法,方法是使用每个索引中的值并将其最后一个数组值链接到下一个对象。如果这是有道理的。

[0, 1, 2, 3, 4, 5, 6]
[0, 1, 2, 3, 6]
[0, 1, 2, 5, 6]
[0, 1, 3, 4, 5, 6]
[0, 1, 3, 4]
[0, 1, 3, 6]
[0, 3, 4, 5, 6]
[0, 3, 6]
[0, 4]

到目前为止,这是我的代码,因为我不知道如何继续进行..

var result = [];
for (var key in obj) {
    var myarr = obj[key];
    for (var i = 0; i < myarr.length; i++) {
        result.push(myarr[i])
    }
}

欢迎任何想法或反馈。

修改

预期结果之一是[0, 1, 2, 3, 4, 5, 6],这是一步一步解释。

  1. obj密钥从0开始,到6结束,我必须形成从06的方式,其值为数组
  2. obj[0]开始,第一个数组返回[0, 1],将其保存到res。 (res现在是[0, 1]
  3. res中数组的最后一个值为1,现在找到obj[1]
  4. 中的下一个值
  5. obj[1]有两个数组,以23结尾。因此可以附加两个数组,因此它可以是{{1} }或[0, 1, 2]。在这种情况下,获取第一个[0, 1, 3]并将最后一个值附加到[1, 2]。 (res现在是res)。
  6. [0, 1, 2]中数组的最后一个值现在是res,现在找到2中的下一个值。
  7. obj[2]有两个数组,以obj[2]3结尾。可以附加两个数组,因此它可以是{{1} }或5。在这种情况下,获取第一个[0, 1, 2, 3]并将最后一个值附加到[0, 1, 2, 5]。 ([2, 3]现在是res
  8. res中数组的最后一个值现在是[0, 1, 2, 3],现在找到res中的下一个值。
  9. 重复步骤4或6.(3现在是obj[3])。
  10. res中数组的最后一个值现在是[0, 1, 2, 3, 4],现在找到res中的下一个值。
  11. 重复步骤4或6.(4现在是obj[4])。
  12. res中数组的最后一个值现在是[0, 1, 2, 3, 4, 5],现在找到res中的下一个值。
  13. 现在找到值5,如果查看步骤obj[5],它应该是迭代的结束。重复步骤4或6.(6现在是4)。
  14. 从步骤1开始重复,并形成另一种方式,没有重复的res

2 个答案:

答案 0 :(得分:8)

这是一个提案,只有一个额外的输出,如下所述。

[
    [0, 1, 2, 3, 4, 5, 6],
    [0, 1, 2, 3, 6],
    [0, 1, 2, 5, 6],
    [0, 1, 3, 4, 5, 6],     /* extended from below                           */
    [0, 1, 3, 4],           /* original result                               */
    [0, 1, 3, 6],
    [0, 3, 4, 5, 6],        /* extended from below                           */
    [0, 3, 4],              /* extra line, line should not be in result      */
    [0, 3, 6],              /* but follows the same building rule than above */
    [0, 4]
]

基本上,此解决方案是使用给定的有关链接节点的信息构建树。

如果某些节点不连续,则会对缺失的链接进行回溯,并使用节点checkNodesiterPath的上述函数来遍历实际收集的节点以查找缺失的项目。 / p>

&#13;
&#13;
function getParts(value, path, nodes) {
    function checkNodes(a) {
        if (a[1] === value + 1) {
            getParts(a[1], path.concat(a[1]), nodes);
            return true;
        }
    }

    function iterPath(k) {
        return (object[k] || []).some(function (a) {
            return path[path.length - 1] + 1 === a[1] || iterPath(a[1]);
        });
    }

    value = value || 0;
    path = path || [value];
    nodes = nodes || [];
    if (object[value]) {
        object[value].forEach(function (a, i, aa) {
            if (a[1] === lastKey) {
                parts.push(path.concat(a[1]));
                return;
            }
            getParts(a[1], path.concat(a[1]), nodes.concat(aa.slice(i + 1)));
        });
        return;
    }
    if (nodes.some(checkNodes)) {
        return;
    }
    path.slice(1).some(iterPath) && getParts(path[path.length - 1] + 1, path.concat(path[path.length - 1] + 1), nodes);
    parts.push(path);
}

var object = {
        0: [[0, 1], [0, 3], [0, 4]],
        1: [[1, 2], [1, 3]],
        2: [[2, 3], [2, 5]],
        3: [[3, 4], [3, 6]],
        5: [[5, 6]],
        6: [[6, 5]]
    },
    lastKey = 6,
    parts = [];

getParts();
parts.forEach(function (a) { console.log(JSON.stringify(a)); });
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;

答案 1 :(得分:2)

好吧,我现在坐在这一段时间了,分享我对这个问题的看法:

输入对象可以被视为树的 邻接列表

var obj={0:[[0,1],[0,3],[0,4]],1:[[1,2],[1,3]],2:[[2,3],[2,5]],3:[[3,4],[3,6]],5:[[5,6]],6:[[6,5]]};

以及所需的结果,实际上,正如我所看到的,树的所有 root-to-leaf路径 的列表: / p>

[0,1,2,3,4]
[0,1,2,3,6]
[0,1,2,5,6]
[0,1,3,4]
[0,1,3,6]
[0,3,4]
[0,3,6]
[0,4]

与问题中提到的结果集略有不同,如下所示:

[0,1,2,3,4,5,6]
[0,1,2,3,6]
[0,1,2,5,6]
[0,1,3,4,5,6]
[0,1,3,4]
[0,1,3,6]
[0,3,4,5,6]
[0,3,6]
[0,4]

结果之间的 差异 只是问题 4和6是否为叶节点

<强>解决方案

所以我假设我们的树在这里:

  1. 0 是根节点

  2. 4 6 是叶节点

  3. 请参阅下面的代码 - 我首先创建了一个树,并从中列出了所有根到叶子路径

    // removed "6:[[6,5]]" as 6 is a 'leaf' of the tree
    var obj={0:[[0,1],[0,3],[0,4]],1:[[1,2],[1,3]],2:[[2,3],[2,5]],3:[[3,4],[3,6]],5:[[5,6]]};
    
    var availableNodes = Object.keys(obj);
    
    var tree = availableNodes.reduce(function(hash) {
      return function(prev, curr) {
        hash[curr] = hash[curr] || {};
        hash[curr].children = hash[curr].children || [];
        obj[curr].forEach(function(element) {
          hash[element[1]] = hash[element[1]] || {};
          hash[element[1]].children = hash[element[1]].children || [];
          hash[curr].rootPath = hash[curr].rootPath || [];
          hash[curr].children.push({value: element[1],children: hash[element[1]].children});
        });
        curr && prev.push({value: curr,children: hash[curr].children});
        return prev;
      };
    }(Object.create(null)), []);
    
    //console.log(JSON.stringify(tree));
    
    var result = [];
    
    function rootToLeafPaths(node, path) {
      path.push(+node.value);
      if (node.children.length === 0) {
        result.push(Array.from(path));
        path.pop();
      } else {
        node.children.forEach(function(element) {
          rootToLeafPaths(element, path);
        });
        path.pop();
      }
    }
    
    rootToLeafPaths(tree[0], []);
    console.log(JSON.stringify(result));
    .as-console-wrapper{top:0;max-height:100%!important;}