2

我想遍历以下数组,并分解为对象,来自:

data = [
  {k: "a_b_c", v: 1},
  {k: "a_b_c", v: 2},
  {k: "a_b_c", v: 3},
  {k: "a_b_d", v: 1},
  {k: "a_b_d", v: 2},
  {k: "a_b_d", v: 3},
  {k: "a_c_a", v: 1},
  {k: "a_c_b", v: 2},
  {k: "a_d", v: 1},
  {k: "a_d", v: 2}
]

至:

result = {
  a: {
    b: {
      c: [1,2,3],
      d: [1,2,3]
    },
    c: {
      a: [1],
      b: [2]
    },
    d: [1,2]
  },
}

关于巧妙地实现这一目标的任何想法?

4

5 回答 5

5

编辑:OP 改变了数据在问题中的呈现方式。以下解决方案对于代码中提到的先前数据是正确的。

您提到的对象无效。不能有重复的键。但是,使用唯一键,这应该是实现此目的的方法:

var result = {};

data = {
  "a_b_c": 1,
  "a_b_c": 2,
  "a_b_c": 3,
  "a_b_d": 1,
  "a_b_d": 2,
  "a_b_d": 3,
  "a_c_a": 1,
  "a_c_b": 2
}


for(the_key in data)
{
    new_keys = the_key.split("_");
    result[new_keys[0]] =  result[new_keys[0]] || {};
    result[new_keys[0]][new_keys[1]] = result[new_keys[0]][new_keys[1]]|| {};
    result[new_keys[0]][new_keys[1]][new_keys[2]] = result[new_keys[0]][new_keys[1]][new_keys[2]] || [];
    result[new_keys[0]][new_keys[1]][new_keys[2]].push(data[the_key]);
}


console.log(result);

演示:http: //jsfiddle.net/8ZbMt/

于 2013-05-09T08:04:51.867 回答
2

这将做到:

var data = [
  {k: "a_b_c", v: 1},
  {k: "a_b_c", v: 2},
  …
]

var result = {};
for (var i=0; i<data.length; i++) {
    var keys = data[i].k.split("_"),
        o = result;
    for (var j=0; j<keys.length-1; j++)
        o = o[keys[j]] || (o[keys[j]] = {});
    o = o[keys[j]] || (o[keys[j]] = []);
    o.push(data[i].v);
}
于 2013-05-09T08:17:35.107 回答
1

您所描述的是一种数据结构,名称为 Trie、Digital Search Tree 或 Retrieval Tree。

这是关于尝试的维基百科文章,它包含构建它们的通用算法。

于 2013-05-09T08:11:51.273 回答
1

这是一些可怕的代码:

var data = [
  {k: "a_b_c", v: 1},
  {k: "a_b_c", v: 2},
  {k: "a_b_c", v: 3},
  {k: "a_b_d", v: 1},
  {k: "a_b_d", v: 2},
  {k: "a_b_d", v: 3},
  {k: "a_c_a", v: 1},
  {k: "a_c_b", v: 2}
];

var result ={};

data.forEach(function(item) {
  var keys = item.k.split("_");
  var entryPoint = result;
  var l = keys.length-1;
  keys.forEach(function(key, index) {
    if (!entryPoint[key])
      entryPoint[key] = (index == l) ? [] : {};
    entryPoint = entryPoint[key];
  });
  entryPoint.push(item.v);
});

如果您在同一级别上同时拥有子键和值,则会失败。(需要一些更改输出格式来修复。)

于 2013-05-09T08:25:22.967 回答
0

我的条目如下:

rslt = data.reduce (function (rslt, d) {
  for (var traverse = rslt, keys = d.k.split ('_'); keys.length > 1;) {
    !traverse.hasOwnProperty (keys[0]) && (traverse[keys[0]] = {});
    traverse = traverse[keys.shift ()];
  }  

  !traverse.hasOwnProperty (keys = keys[0]) && (traverse[keys] = []);
  traverse[keys].push (d.v);
  return rslt;
}, {});
于 2013-05-09T08:42:09.037 回答