根据分组使用源对象数组的属性创建对象数组

时间:2019-10-22 09:56:47

标签: javascript arrays ecmascript-6

我有一个具有以下结构的对象数组:


    let sampleData = [
      { values: { val1: 4, val2: 5, val3: 7 } , time: "1571372233234" , sum: 16 },
      { values: { val1: 5, val2: 3, val3: 1 }, time: "1571372233234" , sum: 9},
      { time: "14354545454", sum: 0},
      { time: "14354545454", sum: 0} }
    ];


我需要获取数组内部每个对象内的每个键,并从中形成一个数组。基本上基于所有对象中存在的键进行分组。如果对象没有“值”,则应该在val1,val2,val3中返回0。

对象的结果数组应如下所示:

result = [
  { name: 'val1', data: [4, 5, 0, 0] }, 
  { name: 'val2', data: [5, 3, 0, 0] }, 
  { name: 'val3', data: [7, 1, 0, 0] }
]

到目前为止,我已经尝试过:

var result = sampleData.map(value => ({ value: value.values }));

1 个答案:

答案 0 :(得分:3)

您可以reduce阵列。创建一个累加器,每个valx作为键,{ name: valx, data: [] }作为其值。遍历每个values的键并更新累加器。然后使用Object.values()获取合并对象的值以获取所需的输出

const sampleData = [
   { values: { val1: 4, val2: 5, val3: 7 } },
   { values: { val1: 5, val2: 3, val3: 1 }},
   { values: { val1: 4, val2: 7, val3: 2 } },
   { values: { val1: 5, val2: 1, val3: 5 } }
];

const merged = sampleData.reduce((acc, { values }) => {
  for (const name in values) {
    acc[name] = acc[name] || { name, data: [] }
    acc[name].data.push(values[name])
  }
  return acc;
}, {})

const output = Object.values(merged)

console.log(output)

更新

如果values是可选的,则可以检查values是否未定义。但是,如果在0不存在时需要values,则需要执行另一步。首先,我们需要获取数组中所有可能的valx键。因为,如果{ time: "14354545454", sum: 0}出现在数组的开头,则无法知道数组中可能存在的键。您可以使用flatMapSet进行此操作。然后遍历每个对象的键集。如果values不存在,请为当前循环的0密钥添加默认的valx

let sampleData = [
   { values: { val1: 4, val2: 5, val3: 7 } , time: "1571372233234" , sum: 16 },
   { values: { val1: 5, val2: 3, val3: 1 }, time: "1571372233234" , sum: 9},
   { time: "14354545454", sum: 0},
   { time: "14354545454", sum: 0}
];

const keySet = new Set( sampleData.flatMap(a => Object.keys(a.values || {})) )

const merged = sampleData.reduce((acc, { values = {} }) => {
  keySet.forEach(name => {
    acc[name] = acc[name] || { name, data: [] }
    acc[name].data.push(values[name] || 0)
  })
  return acc;
}, {})

console.log(Object.values(merged))