按对象属性的总和对一种对象进行排序

时间:2019-12-05 20:06:48

标签: javascript

我的数组看起来像这样

[
  {
    ...
    "code": "X",
    "pricings": [
       {
          "price": 51,
          ...
       },
       {
          "price": 51,
          ...
       }
     ]
   },
   {
     ...
     "code": "Y",
     "pricings": [
       {
         "price": 88,
         ...
       },
       {
         "price": 88,
         ...
       }
    ]
  },
  ...
]

我需要按price属性的总和(降序)进行排序。因此,在此示例中,代码为“ Y”的产品应位于第一个位置。

我目前正在这样做

arr.sort((a, b) => b.pricings.map(el => el.price).reduce((prev, curr) => { return prev + curr }) - a.pricings.map(el => el.price).reduce((prev, curr) => { return prev + curr }))

但是我不太确定这是否是实现此目的的好方法,并且我很好奇是否有一种更简单/更好的解决方案来实现结果。也许您可以分享一些经验:)

3 个答案:

答案 0 :(得分:3)

您可以获取一个包含项总和的数组,并对总和在相同索引处的索引数组进行排序,然后按所需顺序映射一个新数组。

此方法的优点是为每个对象进行一次pricing循环。

var array = [{ code: "X", pricings: [{ price: 51 }, { price: 51 }] }, { code: "Y", pricings: [{ price: 88 }, { price: 88 }] }, { pricings: [{ price: 7 }, { price: 42 }, { price: 33 }] }],
    sums = array.map(({ pricings }) => pricings.reduce((s, { price }) => s + price, 0)),
    result = [...sums.keys()]
        .sort((a, b) => sums[b] - sums[a])
        .map(i => array[i]);

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

答案 1 :(得分:2)

无需先将其映射,只需对归约进行排序:

arr.sort((a, b) => {
  const sumA = a.pricings.reduce((sum, entry) => sum + entry.price, 0);
  const sumB = b.pricings.reduce((sum, entry) => sum + entry.price, 0);
  return sumA - sumB;
});

您甚至可以考虑将数组预处理为一个新数组,其中每个条目都是一个对象,该对象具有预先计算的总和和原始引用,然后进行映射;应该通过在排序过程中不进行多次减少调用来提高性能:

const mapped = arr.map(entry => {
  const sumEntry = entry.pricings.reduce((sum, pricing) => sum + pricing.price, 0);
  return {
    entry,
    sum: sumEntry

  }
});
mapped.sort((a, b) => a.sum - b.sum).map(value => value.entry);

答案 2 :(得分:2)

您的解决方案很好,但是您可以跳过.map()并预先存储reducer函数。

const sumPrice = (acc,val) => acc + val.price;
arr.sort((a, b) => b.pricings.reduce(sumPrice,0) - a.pricings.reduce(sumPrice,0))