创建一个可以处理任意数量具有唯一ID的对象的reduce方法

问题描述 投票:0回答:3

我正在尝试使用reduce方法对对象数组进行排序。我的目标是创建一个可以处理任意数量的对象(具有唯一的 eventId)的 reduce 方法。所需的输出将采用如下格式,但能够处理超过五个唯一的 eventId

[所需输出]

     (5) [{…}, {…}, {…}, {…}, {…}]
       0:
          eventId: "12345"
          total: Array(3)
            0: {total: 123}
            1: {total: 45}
            2: {total: 123}
            length: 3

       1: {total: Array(3), eventId: '12347'}
       2: {total: Array(3), eventId: '12349'}
       3: {total: Array(3), eventId: '12348'}
       4: {total: Array(3), eventId: '12346'}

为了获得上面的输出,我使用了这个reduce方法。

[减少方法]

      const sortedSalesData = salesData.reduce((acc, obj) => {

      for ( let i = 0; i<salesData.length; i++) {

        if (obj.eventId === salesData[i].eventId ) {

          acc[i].eventId = salesData[i].eventId;
          acc[i].total = [...acc[i].total, {total: obj.total}];

          return acc;
        }
      };
      
  },[{total:[]},{total:[]},{total:[]},{total:[]},{total:[]}]);  

但我不确定如何设置它来处理超过这五个唯一的 eventId。以下是原始数组供参考。

[原始数组]

    const salesData = 
    [
      { eventId: '12345', total: 123 },
      { eventId: '12347', total: 45 },
      { eventId: '12349', total: 78 },
      { eventId: '12348', total: 123 },
      { eventId: '12346', total: 45 },
      { eventId: '12349', total: 78 },
      { eventId: '12347', total: 123 },
      { eventId: '12345', total: 45 },
      { eventId: '12348', total: 78 },
      { eventId: '12345', total: 123 },
      { eventId: '12347', total: 45 },
      { eventId: '12346', total: 78 },
      { eventId: '12349', total: 123 },
      { eventId: '12348', total: 45 },
      { eventId: '12346', total: 78 },
     ];     

挂断使其能够处理任意数量的唯一事件,而无需在方法末尾添加额外的 {total:[]}。

javascript arrays javascript-objects reduce
3个回答
0
投票

您想要迭代初始数组(obj),如果 eventId 在该数组上尚不存在(accObj),则将迭代的元素插入到新数组(acc)中,当它确实存在(accObj)时,您想要推送总数当前元素(obj)的对象到新元素(accObj)的总数组中?

我认为这可以满足您的需要:

let array = [
  { eventId: '12345', total: 123 },
  { eventId: '12347', total: 45 },
  { eventId: '12349', total: 78 },
  { eventId: '12348', total: 123 },
  { eventId: '12346', total: 45 },
  { eventId: '12349', total: 78 },
  { eventId: '12347', total: 123 },
  { eventId: '12345', total: 45 },
  { eventId: '12348', total: 78 },
  { eventId: '12345', total: 123 },
  { eventId: '12347', total: 45 },
  { eventId: '12346', total: 78 },
  { eventId: '12349', total: 123 },
  { eventId: '12348', total: 45 },
  { eventId: '12346', total: 78 },
]

let reducedArray = array.reduce((acc, obj) => {
  console.log("Element " + JSON.stringify(obj));
  let accObj = acc.find(accObj => accObj.eventId === obj.eventId);
  if(accObj != undefined) {
    console.log("Found element: " + JSON.stringify(accObj) + ".")
    console.log("Pushing "+ obj.total +" to total.")
    accObj.total.push(obj.total);
  } else {
    accObj = { eventId: obj.eventId, total: [obj.total] };
    console.log("Pushing new element to list: " + JSON.stringify(accObj));
    acc.push(accObj);
  }
  return acc;
}, []);

console.log(JSON.stringify(reducedArray));

技巧在于

find
方法,我正在搜索自己的缩减列表,看看它是否已经有一个与旧数组共享 eventId 的元素。


0
投票

我不喜欢 .reduce 所以这是一个没有它的简单解决方案

    const salesData = 
    [
      { eventId: '12345', total: 123 },
      { eventId: '12347', total: 45 },
      { eventId: '12349', total: 78 },
      { eventId: '12348', total: 123 },
      { eventId: '12346', total: 45 },
      { eventId: '12349', total: 78 },
      { eventId: '12347', total: 123 },
      { eventId: '12345', total: 45 },
      { eventId: '12348', total: 78 },
      { eventId: '12345', total: 123 },
      { eventId: '12347', total: 45 },
      { eventId: '12346', total: 78 },
      { eventId: '12349', total: 123 },
      { eventId: '12348', total: 45 },
      { eventId: '12346', total: 78 },
     ]
     
     let reduced = {}
     salesData.forEach(elem=> {
       if(reduced[elem.eventId] !== undefined){
         reduced[elem.eventId].push(elem.total)
       } else {
         reduced[elem.eventId] = [elem.total]
       }
     })
     reduced = Object.keys(reduced).map(elem => {
       return({eventId: elem, total:reduced[elem]})
     })
     console.log(reduced)


0
投票

在JeanJacquesGourdin的答案的基础上我想添加一个带有reduce的解决方案,它应该比这两个答案(在撰写本文时)性能更高一些。

我只能鼓励大家进入减少的心态。一旦理解了,使用起来就相当容易了。

const array = [
  {eventId: '12345', total: 123},
  {eventId: '12347', total: 45},
  {eventId: '12345', total: 45},
]

const output = Object.entries(array.reduce((acc, obj) => {
  if (!acc[obj.eventId]) {
    acc[obj.eventId] = []
  }
  acc[obj.eventId].push(obj.total)
  return acc;
}, {})).map(([eventId, total]) => ({
  eventId,
  total
}));

console.log(output);

我唯一不喜欢这种方法的是

Object.entries
,它看起来很不合适并且破坏了管道流动。然而,它的性能更高,而且在我看来,也更容易阅读。

© www.soinside.com 2019 - 2024. All rights reserved.