繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM