首页 > 解决方案 > 使用 reduce 转换数组(属性未定义)

问题描述

我想转换一个数组以重新组合同一个国家的所有城市。我有一个对象数组

locations = [
{
cities: ["Paris"]
country: "France"
},
{
cities: ["Marseille"]
country: "France"
},
{
cities: ["Kiev"]
country: "Ukraine"
},
{
cities: ["Odessa"]
country: "Ukraine"
}
...

我想要这个:

locations = [
{
cities: ["Paris", "Marseille"]
country: "France"
},
{
cities: ["Kiev, Odessa"]
country: "Ukraine"
},
...

所以,我的想法是:

locations.reduce((prev, curr) => {
    if (prev.country === curr.country) {
      prev.cities.push(curr.cities[0])
      // and delete curr Object
    }
  })

对于第一对等于国家/地区,curr.cities[0] 被推送到 prev.cities,但不会用于下一次迭代:TypeError: Cannot read property 'country' of undefined

[![console.log(locations) - TypeError: Cannot read property 'country' of undefined][1]][1]

标签: javascriptarraysfilterfunctional-programmingreduce

解决方案


使用时reduce,需要返回prev以供下一次迭代使用,同时初始化为{}。此外,您需要注意每个国家/地区的初始添加,其中cities应存储带有数组的对象:

const locations = [
  { country: "France", cities: ['city1','city2'] },
  { country: "France", cities: ['city3','city4'] },
  { country: "Ukraine", cities: ['city5'] },
  { country: "Ukraine", cities: ['city6'] }
];

const res = Object.values(locations.reduce((prev, curr) => {
  const { country, cities = [] } = curr;
  const [city] = cities;
  if (prev[country] && city) {
    prev[country].cities.push(city);
  } else {
    prev[country] = { country, cities: city ? [city] : [] };
  }
  return prev;
}, {}));

console.log(res);


推荐阅读