通过以特定顺序使用对象源数组中的属性进行分组来形成数组

Forming an array by grouping using the properties from source array of objects in a particular order

我有一组具有以下结构的对象作为响应发送:


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


我需要获取数组中每个对象中的每个键并从中形成一个数组。基本上根据所有 objects.If 中存在的键进行分组,对象没有 "values" 它应该 return 0 跨越 val1、val2、val3。

但是问题,问题中 "values" 对象中的键 "high,low,medium" 的顺序是不可预测的。使用我编写的任何代码,第一个对象中存在的键将被分组并遵循该顺序。但我想要它是任何输入命令,它应该总是给我这个命令 "High Medium Low" Order.

生成的对象数组应该看起来像并且应该始终遵循 "High Medium Order":

result = [
  { name: 'High', data: [4, 5, 0, 0] }, 
  { name: 'Medium', data: [5, 3, 0, 0] }, 
  { name: 'Low', data: [7, 1, 0, 0] }
]

我试过以下方法:

let sampleData = [{ values: { High: 4, Low: 5,  Medium: 7 } , time: "1571372233234" , sum: 16 },{ values: { High: 5, Low: 3, Medium : 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(merged);

您可以获取结果集并迭代键和数组的值。

let sampleData = [{ values: { High: 4, Low: 5,  Medium: 7 }, time: "1571372233234", sum: 16 }, { values: { High: 5, Low: 3, Medium : 1 }, time: "1571372233234", sum: 9 }, { time: "14354545454", sum: 0 }, { time: "14354545454", sum: 0 }],
    keys = ['High', 'Low', 'Medium'],
    grouped = sampleData.reduce((r, { values = {} } = {}) => {
        r.forEach(({ name, data }) => data.push(values[name] || 0));
        return r;
    }, keys.map(name => ({ name, data: [] })));

console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

当属性 values 不存在时,您可以检查 undefined 值。

sampleData.reduce((a, {values: {High = 0, Low = 0, Medium = 0} = {}})
                                                               ^
                                                               |
                                                               +-- When attr "values" is 
                                                                   undefined initialize
                                                                   as an "empty" object.

let sampleData = [{ values: { High: 4, Low: 5,  Medium: 7 } , time: "1571372233234" , sum: 16 },{ values: { High: 5, Low: 3, Medium : 1 }, time: "1571372233234" , sum: 9},{ time: "14354545454", sum: 0},{ time: "14354545454", sum: 0}];
    
let result = Object.values(sampleData.reduce((a, {values: {High = 0, Low = 0, Medium = 0} = {}}) => {
  (a["High"] || (a["High"] = {name: "High", data: []})).data.push(High);
  (a["Low"] || (a["Low"] = {name: "Low", data: []})).data.push(Low);
  (a["Medium"] || (a["Medium"] = {name: "Medium", data: []})).data.push(Medium);

  return a;
}, Object.create(null)));
    
 console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

您正在返回一个对象,因此不能保证键的顺序。您可能需要一个数组而不是一个对象。

你可以像这样构造一个最终的 merged 对象

mergedFinal = [ merged['High'], merged['Medium'], merged['Low'] ]