使用 map/reduce 简化复杂的对象数组

Use map/reduce to simplify complex array of object

提问人:GD19 提问时间:10/24/2023 最后编辑:evolutionxboxGD19 更新时间:10/24/2023 访问量:75

问:

我正在尝试使用reduce来获取一个对象数组并以低于预期格式返回一个对象。能够使用它基于 validFrom 创建对象,但无法可视化后续步骤。也尝试使用地图,但没有多大帮助。帮助将不胜感激!如果有帮助,可以共享stackblitz。

尝试过这个来简化,但卡在下一步。第一条评论

inputArray:
[
  {
    "day": "Wednesday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Tuesday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Sunday",
    "closeTime": "1630",
    "openTime": "0845",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Thursday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Friday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Saturday",
    "closeTime": "1630",
    "openTime": "0845",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Monday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  }
]

使用的代码:

let clubbedArray = normalData.reduce((acc, temp) => { let { validFrom, day } = temp; return {...acc, [validFrom]: [...(acc[validFrom] || []), day]}; }, {});

预期输出:

[
  {
    "day": [
      "Friday",
      "Wednesday",
      "Monday",
      "Tuesday",
      "Thursday"
    ],
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": [
      "Saturday",
      "Sunday"
    ],
    "closeTime": "1630",
    "openTime": "0845",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  }
]
javascript 数组 angular reduce 高阶函数

评论

0赞 GD19 10/24/2023
let clubbedArray = normalData.reduce((acc, temp) => { let { validFrom, day } = temp; return {...acc, [validFrom]: [...(acc[validFrom] ||[]), 天]};}, {});
0赞 Pointy 10/24/2023
您不必进行堆栈闪电战。您可以在此处创建一个可运行的代码段,作为问题的一部分。

答:

1赞 Yves Kipondo 10/24/2023 #1

您可以使用函数根据需要更改数组上的形状,这是允许您更改数据形状的代码Array.prototype.reduce

let data = [
  {
    "day": "Wednesday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Tuesday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Sunday",
    "closeTime": "1630",
    "openTime": "0845",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Thursday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Friday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Saturday",
    "closeTime": "1630",
    "openTime": "0845",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Monday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  }
];

const result = data.reduce((accumulator, current) => {
   /*
       Check if there is an object on the result array with the corresponding closeTime if that is the case we return it index
   */
   let exists = accumulator.findIndex(item => {
       return item.closeTime == current.closeTime;
   })
   
   // if there is not item with that closeTime the result of the findIndex will be `-1` if so we add an object with the corresponding closeTime with all property of the `current` item of the reduce loop
   if(exists === -1) {
       accumulator = accumulator.concat({
          day: [current.day],
          closeTime: current.closeTime,
          openTime: current.openTime,
          validFrom: current.validFrom,
          validTo: current.validTo,
       })
   } else {
       accumulator[exists].day.push(current.day);
   }
   return accumulator;
}, []);

console.log(result);

评论

1赞 GD19 10/24/2023
谢谢@Yves,我错过了concat。再次感谢您的 propmt 解决方案。
0赞 mandy8055 10/24/2023 #2

伪代码:

1. Use the reduce() method to iterate over the array.
2. Check if the current object matches any of the existing objects in the accumulator array (acc). -- iterate
     2.1. If the properties match: 
         2.1.1. Add the current object's day property to the matching object's day array.
         2.1.1. else, we create a new object with the current object's properties and push it to the acc array.
3. Return the accumulator array.

实现:

const normalData = [{
    "day": "Wednesday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Tuesday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Sunday",
    "closeTime": "1630",
    "openTime": "0845",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Thursday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Friday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Saturday",
    "closeTime": "1630",
    "openTime": "0845",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  },
  {
    "day": "Monday",
    "closeTime": "2000",
    "openTime": "0800",
    "validFrom": "2001-09-19",
    "validTo": "2099-12-31"
  }
];

const combinedData = normalData.reduce((acc, curr) => {
  let found = false;
  acc.forEach((item) => {
    if (
      item.closeTime === curr.closeTime &&
      item.openTime === curr.openTime &&
      item.validFrom === curr.validFrom &&
      item.validTo === curr.validTo
    ) {
      item.day.push(curr.day);
      found = true;
    }
  });
  if (!found) {
    acc.push({
      day: [curr.day],
      closeTime: curr.closeTime,
      openTime: curr.openTime,
      validFrom: curr.validFrom,
      validTo: curr.validTo,
    });
  }
  return acc;
}, []);

console.log(combinedData);

评论

1赞 GD19 10/24/2023
非常感谢您的解决方案也适用于其他方案@mandy8055。