[英]How to iterate through a nested object and putting values into an array?
我创建了一个包含以下格式的嵌套对象:
var lineMap = {
2016: {
Hemoglobin: 33 ,
Lysozyme: 33 ,
Myoglobin: 47 ,
DNA: 13 ,
Cytochrome C: 33
},
2017: {
Hemoglobin: 8 ,
Lysozyme: 47 ,
Myoglobin: 8 ,
DNA: 12 ,
Cytochrome C: 33
},
2018: {
Hemoglobin: 8 ,
Lysozyme: 33 ,
Myoglobin: 47 ,
DNA: 12 ,
Cytochrome C: 13
},
2019: {
Hemoglobin: 8 ,
Lysozyme: 8 ,
Myoglobin: 47 ,
DNA: 8 ,
Cytochrome C: 47
}
}
而且我想将每年的项目计数放入其自己的数组索引中,以便:
var arr = [
[33, 33, 47, 13, 33],
[8, 47, 8, 12, 33],
[8, 33, 47, 12, 13],
[8, 8, 47, 8, 47]
]
我尝试创建一个嵌套的 for 循环来遍历嵌套对象lineMap
。
for (var i = 0; i < year.length; i ++){
for (var j = 0; j < itemName.length; j++){
temp_arr[j] = lineMap[year[i]][itemName[j]];
}
console.log("Index: " + i + "\n" + temp_arr);
arr[i] = temp_arr;
}
console.log(arr);
在第 5 行( console.log(temp_arr)
),控制台打印出我所期望的——其各自迭代的项目计数数组:
'Index: 0
33,33,47,13,33'
'Index: 1
8,47,8,12,33'
'Index: 2
8,33,47,12,13'
'Index: 3
8,8,47,8,47'
但是,在第 8 行( console.log(arr)
),我没有收到预期的输出。 相反,我得到:
var arr = [
[8, 8, 47, 8, 47],
[8, 8, 47, 8, 47],
[8, 8, 47, 8, 47],
[8, 8, 47, 8, 47]
]
首先,警告:从 ES2015 开始,这些对象中属性的顺序现在已定义,但依赖该顺序通常是一个坏主意。 此外,您似乎只使用 ES5 级别的功能,这些功能没有定义顺序。
因此,最好的方法,不依赖于顺序,是按照你希望它们在结果数组中的顺序给自己一个属性名称数组:
var keys = [
"Hemoglobin",
"Lysozyme",
"Myoglobin",
"DNA",
"Cytochrome C"
];
然后是这样的(见评论):
// Loop through the years sorted lexicographically, building the result array
var arr = Object.keys(lineMap).sort().map(function(mainKey) {
// Loop through the property names in the defined order, building
// each inner array
var entry = lineMap[mainKey];
return keys.map(function(key) {
return entry[key];
});
});
现场示例:
var keys = [ "Hemoglobin", "Lysozyme", "Myoglobin", "DNA", "Cytochrome C" ]; var lineMap = { 2016: { Hemoglobin: 33 , Lysozyme: 33 , Myoglobin: 47 , DNA: 13 , "Cytochrome C": 33 }, 2017: { Hemoglobin: 8 , Lysozyme: 47 , Myoglobin: 8 , DNA: 12 , "Cytochrome C": 33 }, 2018: { Hemoglobin: 8 , Lysozyme: 33 , Myoglobin: 47 , DNA: 12 , "Cytochrome C": 13 }, 2019: { Hemoglobin: 8 , Lysozyme: 8 , Myoglobin: 47 , DNA: 8 , "Cytochrome C": 47 } }; // Loop through the years sorted lexicographically, building the // result array var arr = Object.keys(lineMap).sort().map(function(mainKey) { // Loop through the property names in the defined order, building // each inner array var entry = lineMap[mainKey]; return keys.map(function(key) { return entry[key]; }); }); console.log(arr);
如果你想要数字顺序的年份,只需添加一个回调到sort
:
.sort(function(a, b) { return a - b; })
在 ES2015+ 世界中解决这个问题,我仍然会按照你想要的顺序保留单独的键列表,所以没有太多变化,它只是变得更简洁:
const arr = Object.entries(lineMap)
.sort(([a], [b]) => a.localeCompare(b))
.map(([_, entry]) => keys.map(key => entry[key]));
现场示例:
const keys = [ "Hemoglobin", "Lysozyme", "Myoglobin", "DNA", "Cytochrome C" ]; const lineMap = { 2016: { Hemoglobin: 33 , Lysozyme: 33 , Myoglobin: 47 , DNA: 13 , "Cytochrome C": 33 }, 2017: { Hemoglobin: 8 , Lysozyme: 47 , Myoglobin: 8 , DNA: 12 , "Cytochrome C": 33 }, 2018: { Hemoglobin: 8 , Lysozyme: 33 , Myoglobin: 47 , DNA: 12 , "Cytochrome C": 13 }, 2019: { Hemoglobin: 8 , Lysozyme: 8 , Myoglobin: 47 , DNA: 8 , "Cytochrome C": 47 } }; const arr = Object.entries(lineMap) .sort(([a], [b]) => a.localeCompare(b)) .map(([_, entry]) => keys.map(key => entry[key])); console.log(arr);
这利用了Object.entries
、 箭头函数和解构赋值。
再说一次,如果你想按数字顺序排列这些年份:
const arr = Object.entries(lineMap)
.sort(([a], [b]) => a - b)
.map(([_, entry]) => keys.map(key => entry[key]));
你的问题看起来像问题出在arr[i] = temp_arr;
并共享相同的数组引用。 您需要在每次迭代时从一个新数组开始。 或者你需要在复制它时克隆它。 arr[i] = temp_arr.slice(0)
Object.entries 和 map() 将使您的工作更轻松。
var lineMap = { 2016: { Hemoglobin: 33, Lysozyme: 33, Myoglobin: 47, DNA: 13, 'Cytochrome C': 33 }, 2017: { Hemoglobin: 8, Lysozyme: 47, Myoglobin: 8, DNA: 12, 'Cytochrome C': 33 }, 2018: { Hemoglobin: 8, Lysozyme: 33, Myoglobin: 47, DNA: 12, 'Cytochrome C': 13 }, 2019: { Hemoglobin: 8, Lysozyme: 8, Myoglobin: 47, DNA: 8, 'Cytochrome C': 47 } } console.log(Object.values(lineMap).map(o=>Object.values(o)))
首先,使用的是完全一样的阵列每一次,所以当你arr[i] = temp_arr
要分配相同副本的每个位置arr
。 您应该每次都创建一个新数组。 其次,您无法知道对象键的顺序,不能保证在迭代键时键会被排序。 话虽如此,您仍然可以使用固定的键列表或先对它们进行排序。
let orderedKeys = ['Hemoglobin', 'Lysozyme', 'Myoglobin', 'DNA', 'Cytochrome C'];
let arr = Object.values(lineMap).map(el => orderedKeys.map(k => el[k]))
结果:
> arr
0: [33, 33, 47, 13, 33]
1: [8, 47, 8, 12, 33]
2: [8, 33, 47, 12, 13]
3: [8, 8, 47, 8, 47]
如果您对 ES6 语法没问题,这将解决问题:
let result = [];
Object.values(lineMap).map(obj =>result.push(Object.values(obj)))
这将为您提供您想要的数组数组。 如果您更喜欢包含所有结果的单个数组,您可以像这样传播第二个Object.values(obj)
:
Object.values(lineMap).map(obj =>result.push(...Object.values(obj)))
我创建了一个名为yearsItemCount()的函数; 只需调用它,它就会返回你想要的......虽然它是 O(N^2)
yearsItemCount = () => {
let finalArr = []
for(var line in lineMap) {
let arr = [];
for(var i in lineMap[line]) {
arr.push(lineMap[line][i])
}
finalArr.push(arr);
}
return finalArr;
}
或者
Object.values(lineMap).map((a, b) => {
return Object.values(a);
})
我不知道什么更快。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.