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

时间:2019-07-24 15:02:54

标签: 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
  },
  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]
]

5 个答案:

答案 0 :(得分:1)

首先,警告:现在,从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.entriesarrow functionsdestructuring assignment的优势。

再次,如果您想按数字顺序排列年份:

const arr = Object.entries(lineMap)
    .sort(([a], [b]) => a - b)
    .map(([_, entry]) => keys.map(key => entry[key]));

答案 1 :(得分:0)

您的问题似乎是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)))

答案 2 :(得分:0)

首先,您每次都使用完全相同的数组,因此当您执行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]

答案 3 :(得分:0)

如果您对ES6语法没问题,那么就可以解决问题:

f(t)

这将为您提供所需的数组数组。如果您希望使用具有所有结果的单个数组,则可以像这样分散第二个ν = ±Ν / 2 = ±1 / (2 Δt)

f(t)

答案 4 :(得分:0)

我创建了一个名为 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);
})

我不知道什么更快。