Javascript 如何遍历嵌套对象并将值放入数组?

Javascript 如何遍历嵌套对象并将值放入数组?,javascript,arrays,object,Javascript,Arrays,Object,我创建了一个嵌套对象,其格式如下: 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 }

我创建了一个嵌套对象,其格式如下:

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);
但是,在第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]
]

您的问题似乎是
arr[i]=temp\u arr和共享相同的数组引用。每次迭代都需要从一个新数组开始。或者复制时需要克隆它<代码>阵列[i]=温度阵列切片(0)

Object.entries和map()将使您的工作更轻松

var lineMap={
2016: {
血红蛋白:33,
溶菌酶:33,
肌红蛋白:47,
DNA:13,
“细胞色素C”:33
},
2017: {
血红蛋白:8,
溶菌酶:47,
肌红蛋白:8,
DNA:12,
“细胞色素C”:33
},
2018: {
血红蛋白:8,
溶菌酶:33,
肌红蛋白:47,
DNA:12,
“细胞色素C”:13
},
2019: {
血红蛋白:8,
溶菌酶:8,
肌红蛋白:47,
DNA:8,
“细胞色素C”:47
}
}

console.log(Object.values(lineMap).map(o=>Object.values(o))
首先,一个警告:从ES2015开始,这些对象中属性的顺序已经定义,但依赖于该顺序通常是个坏主意。此外,您似乎只使用ES5级别的功能,而这些功能并没有定义顺序

所以,在不依赖顺序的情况下,最好的方法是按照希望属性名称在结果数组中的顺序为自己指定一个属性名称数组:

var keys = [
    "Hemoglobin",
    "Lysozyme",
    "Myoglobin",
    "DNA",
    "Cytochrome C"
];
然后像这样(见评论):

实例:

var键=[
“血红蛋白”,
“溶菌酶”,
“肌红蛋白”,
“DNA”,
“细胞色素C”
];
变量行映射={
2016: {
血红蛋白:33,
溶菌酶:33,
肌红蛋白:47,
DNA:13,
“细胞色素C”:33
},
2017: {
血红蛋白:8,
溶菌酶:47,
肌红蛋白:8,
DNA:12,
“细胞色素C”:33
},
2018: {
血红蛋白:8,
溶菌酶:33,
肌红蛋白:47,
DNA:12,
“细胞色素C”:13
},
2019: {
血红蛋白:8,
溶菌酶:8,
肌红蛋白:47,
DNA:8,
“细胞色素C”:47
}
};
//按字典顺序循环这些年,构建
//结果数组
var arr=Object.keys(lineMap).sort().map(函数(mainKey){
//按定义的顺序循环浏览属性名称,即building
//每个内部数组
var条目=线条图[main key];
返回键。映射(函数(键){
返回条目[键];
});
});

控制台日志(arr)
首先,您每次都使用完全相同的数组,因此当您执行
arr[i]=temp\u 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)


我不知道什么更快。

您的线图是json,也许可以尝试包含这些信息,您可以更高效地迭代json对象。您可以使用
Object.values(lineMap.values)
@RedaDrissi-“您的lineMap是json”不,它不是。JSON是用于数据交换的文本表示法。如果您处理的是JavaScript源代码,而不是字符串,那么您就不是在处理JSON。@MaheerAli-我肯定我们以前有过这样的对话。:-)JavaScript对象中属性的顺序现在已经定义,所以“您无法按顺序获取它们”是不正确的。你不应该把它们整理好,是的,但是…:-)@请原谅我的语言滥用,linemap类似于解析的JSON字符串,因此可以更高效地对其进行迭代。
let result = [];
Object.values(lineMap).map(obj =>result.push(Object.values(obj)))
Object.values(lineMap).map(obj =>result.push(...Object.values(obj)))
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);
})