按对象中数组的总和排序

时间:2019-06-14 13:04:46

标签: javascript arrays sorting

我正在寻找一种解决方案,可以根据对象内的数组属性的总和对数组进行排序。

例如,如果主数组是

[
  {
    "Grid": {
       "Day": [
          11,
          12
       ]
     },
     "Name": "One"
  },
  {
    "Grid": {
       "Day": [
          5,
          2
       ]
     },
     "Name": "Two"
   }
]

如何对Day的总和进行排序以返回为

[
  {
    "Grid": {
       "Day": [
          5,
          2
       ]
     },
     "Name": "Two"
  },
  {
    "Grid": {
       "Day": [
          11,
          12
       ]
     },
     "Name": "One"
   }
]

4 个答案:

答案 0 :(得分:3)

您可以结合使用reduce和数组sort对输出求和:

var input = [
  {
    "Grid": {
       "Day": [
          11,
          12
       ]
     },
     "Name": "One"
  },
  {
    "Grid": {
       "Day": [
          5,
          2
       ]
     },
     "Name": "Two"
   }
];


var result = input.sort( (a,b) =>  sumOfDay(a) - sumOfDay(b));
console.log(result);

function sumOfDay(obj){
    return obj.Grid.Day.reduce( (acc,curr) => acc + curr, 0);
}

请注意,Array.prototype.sort实际上是对原始数组进行了适当的突变。所以上面也可以做

input.sort( (a,b) =>  sumOfDay(a) - sumOfDay(b));
console.log(input);

因此,不要仅仅因为我将结果分配给result!就陷入了认为原始数组没有改变的陷阱。

如果您希望对数组的副本进行排序,请执行以下操作:

var result = input.slice().sort( (a,b) =>  sumOfDay(a) - sumOfDay(b));

答案 1 :(得分:2)

您只需要sort带有比较器的数组,该比较器就使用reduce来计算内部数组值的总和:

let arr = [{"Grid": {"Day": [11,12]}, "Name": "One"},
           {"Grid": {"Day": [5,2]}, "Name": "Two"},
           {"Grid": {"Day": [1,2]}, "Name": "Two"}];
           
let sum = el => el.Grid.Day.reduce((a,b) => a + b);
arr.sort((a,b) => sum(a) - sum(b));

console.log(arr)

答案 2 :(得分:0)

通过映射创建一个新的a数组,并在reduce的{​​{1}}数组上使用Day以获取您可以在{{ 1}},以按天数排序返回您的列表。

Grid

答案 3 :(得分:0)

仅通过“另一种”方法即可解决此问题:假设您(某天,以后,最终)可能需要再次排序,一种好的方法还可能是在每个网格项中添加一个保存天数之和的属性,避免每次需要对数组进行排序时,都会调用.reduce。

在这种方法中,.forEach用于创建新属性(通过.reduce),然后.sort用于对数组进行就地排序。

const input = [
  {
    "Grid": {
       "Day": [
          11,
          12
       ]
     },
     "Name": "One"
  },
  {
    "Grid": {
       "Day": [
          5,
          2
       ]
     },
     "Name": "Two"
   }
];
// Add a DaySum property evaluating the sum of the days.
input.forEach(i => i.Grid.DaySum = i.Grid.Day.reduce((a,b) => a + b));
//                                                                 ^--- the second parameter (initial value) is unneeded here due to the fact that all elements are actually numeric, hence if the initial value is the first element of the array, which is a number already.
// Sor the array by that property.
input.sort((a,b) => a.Grid.DaySum - b.Grid.DaySum);
console.log(input);

或者,如下面@Andreas所建议的那样,您可以在排序时直接分配属性:

const input = [
  {
    "Grid": {
       "Day": [
          11,
          12
       ]
     },
     "Name": "One"
  },
  {
    "Grid": {
       "Day": [
          5,
          2
       ]
     },
     "Name": "Two"
   }
];

const sum = (a,b) => a + b;
input.sort((a,b) => {
  a.Grid.DaySum = a.Grid.DaySum || a.Grid.Day.reduce(sum);
  b.Grid.DaySum = b.Grid.DaySum || b.Grid.Day.reduce(sum);
  return a.Grid.DaySum - b.Grid.DaySum;
});
console.log(input);