【问题标题】:Transform array using reduce (property undefined)使用 reduce 转换数组(属性未定义)
【发布时间】:2021-03-30 02:56:51
【问题描述】:

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

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
    }
  })

对于第一对 equals 国家,curr.cities[0] 被推送到 prev.cities,但不用于下一次迭代: TypeError:无法读取未定义的属性“国家/地区”

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

【问题讨论】:

  • 您能否分享每个cities 数组中的值以及您在转换对象后尝试获得的结果?
  • 你不会从 reduce 内部函数返回 prev。所以在下一次迭代中 prev 不存在。

标签: javascript arrays filter functional-programming reduce


【解决方案1】:

我认为要实现所需的输出格式,您可以执行以下操作:

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

var grouped = Object.entries(
  locations.reduce((a, {country, cities}) => ({
    ...a, [country]: [...(a[country] || []), ...cities]
  }), {})
).map(([country, cities]) => ({ country: country, cities: cities }), []);
  
console.log(grouped);

【讨论】:

    【解决方案2】:

    使用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);

    【讨论】:

      【解决方案3】:

      您可以创建一个以国家/地区为键的地图,并以最初为空的数组作为对应值。然后填充这些数组,最后从该 Map 中提取条目。这具有线性时间复杂度:

      let locations = [{cities: ["Paris"],country: "France"},{cities: ["Marseille"],country: "France"},{cities: ["Kiev"],country: "Ukraine"},{cities: ["Odesa"], country: "Ukraine"}];
      
      let map = new Map(locations.map(({country}) => [country, {country, cities: []}]));
      for (let loc of locations) map.get(loc.country).cities.push(...loc.cities);
      let res = Array.from(map.values());
      
      console.log(res);

      【讨论】:

        猜你喜欢
        • 2020-11-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-26
        • 1970-01-01
        • 2021-12-27
        • 1970-01-01
        • 2021-10-30
        相关资源
        最近更新 更多