我正在尝试使用现有数据集创建嵌套树对象。 原始数据集是:
var raw_data = [
["A1", "B1", "C1", 1],
["A1", "B1", "C2", 2],
["A1", "B2", "C1", 3],
["A1", "B2", "C1", 4],
["A1", "B2", "C2", 5],
["A1", "B2", "C2", 6],
["A2", "B1", "C1", 7],
["A2", "B1", "C1", 8],
["A2", "B1", "C2", 9],
["A2", "B1", "C2", 10],
["A2", "B2", "C1", 11],
["A2", "B2", "C1", 12],
["A2", "B2", "C2", 13],
["A2", "B2", "C2", 14]
];
我希望我的最终数据看起来像这样:
{'A1':
{'B1': {'C2': 2, 'C1': 1},
'B2': {'C2': 6, 'C1': 4}
},
'A2':
{'B1': {'C2': 10, 'C1': 8},
'B2': {'C2': 14, 'C1': 12}
}
}
到目前为止,这是我的进度。
var obj = {};
for(i = 0; i< raw_data.length; i++) {
var [x,y,z,value] = raw_data[i];
obj[x][y][z] = value;
}
我遍历数据并在空数据上递归运行属性值。
例如:在第一次迭代中,我设置了obj['A1']['B1']['C1'] = 1
。
但是,这会引起问题,因为第一个递归(obj['A1'
]将返回undefined
,因此出现以下错误:
"TypeError: Cannot set property 'B1' of undefined
为解决此问题,我尝试像这样在ES6中使用var obj = {}
对象,而不是proxy
:
var obj = new Proxy({}, {
get: function(target, name) {
if (!(name in target)) {
console.log("Non-existant property '" + name + "'");
var val = target[name] = typeof(target); //Returning reference to already created object
return val;
}
}
});
但是,现在返回以下错误: “ TypeError:无法设置未定义的属性'C1'
我在这里做什么错了?
答案 0 :(得分:1)
您可以使用动态方法,将给定的键减少到最后一个元素,并将其用作分配值的访问器。
除了获得正确的内部对象之外,如果对象不存在,则会将默认对象分配给属性。
function setValue(object, path, value) {
var last = path.pop();
path.reduce((o, k) => o[k] = o[k] || {}, object)[last] = value;
return object;
}
var raw_data = [["A1", "B1", "C1", 1], ["A1", "B1", "C1", 2], ["A1", "B1", "C2", 3], ["A1", "B2", "C1", 4], ["A1", "B2", "C1", 5], ["A1", "B2", "C2", 6], ["A1", "B2", "C2", 7], ["A2", "B1", "C1", 8], ["A2", "B1", "C1", 9], ["A2", "B1", "C2", 10], ["A2", "B1", "C2", 11], ["A2", "B2", "C1", 12], ["A2", "B2", "C1", 13], ["A2", "B2", "C2", 14], ["A2", "B2", "C2", 15]],
object = raw_data.reduce((r, a) => setValue(r, a.slice(0, -1), a[a.length - 1]), {});
console.log(object);
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 1 :(得分:1)
使用ES6,您可以做到
for(i = 0; i< raw_data.length; i++) {
var [x,y,z,value] = raw_data[i];
obj[x] && obj[x][y] ? obj[x][y][z] = value : obj[x] ? obj[x][y] = {[z] : value} : obj[x] = {[y] : {[z] : value}};
}
感谢 ComputedPropertyName (请参见https://stackoverflow.com/a/2274327/3057341)
答案 2 :(得分:0)
这是我针对您问题的代码解决方案。我遍历了数组数组中的每个元素,并按照嵌套结构填充了对象。
const raw_data = [
["A1", "B1", "C1", 1],
["A1", "B1", "C2", 2],
["A1", "B2", "C1", 3],
["A1", "B2", "C1", 4],
["A1", "B2", "C2", 5],
["A1", "B2", "C2", 6],
["A2", "B1", "C1", 7],
["A2", "B1", "C1", 8],
["A2", "B1", "C2", 9],
["A2", "B1", "C2", 10],
["A2", "B2", "C1", 11],
["A2", "B2", "C1", 12],
["A2", "B2", "C2", 13],
["A2", "B2", "C2", 14]
];
let obj = {};
raw_data.forEach(element => {
for(let i=0; i<4; i++){
let first_elem = element[0];
let second_elem = element[1];
let third_elem = element[2];
let fourth_elem = element[3];
switch(i){
case 0:
if(!(first_elem in obj)){
obj[first_elem] = {};
}
break;
case 1:
if(!(second_elem in obj[first_elem])){
obj[first_elem][second_elem] = {};
}
break;
case 2:
if(!(third_elem in obj[first_elem][second_elem])){
obj[first_elem][second_elem][third_elem] = null;
}
break;
case 3:
if(fourth_elem != obj[first_elem][second_elem][third_elem]){
obj[first_elem][second_elem][third_elem] = fourth_elem;
}
break;
}
}
});
console.log(obj);