【问题标题】:Build required array of objects using Filter and Reduce使用 Filter 和 Reduce 构建所需的对象数组
【发布时间】:2019-05-06 15:28:15
【问题描述】:

我有以下示例数据,它们是三个对象数组,即:

let dets = [
  {
    "id": 1,
    "name":"tom",
    "country":"USA",
    "phone": "1234"
  },
  {
    "id": 2,
    "name":"sarah",
    "country":"ITALY",
    "phone": "8899"
  },
  {
    "id": 3,
    "name":"harry",
    "country":"GERMANY",
    "phone": "3434"
  }  
];

let foods = [
  {
    "id": 1,
    "food":"pizza"
  },
  {
    "id": 1,
    "name":"pasta"
  },
  {
    "id": 1,
    "name":"oranges"
  },  
  {
    "id": 2,
    "name":"donuts"
  },  
  {
    "id": 2,
    "name":"pizza"
  },
  {
    "id": 2,
    "name":"apples"
  },
  {
    "id": 3,
    "name":"apples"
  },
  {
    "id": 3,
    "name":"strawberries"
  }
];

let musics = [
  {
    "id": 1,
    "music":"jazz"
  },
  {
    "id": 1,
    "music":"funk"
  },
  {
    "id": 1,
    "music":"country"
  },  
  {
    "id": 2,
    "music":"jazz"
  },  
  {
    "id": 2,
    "music":"rock"
  },
  {
    "id": 2,
    "music":"heavy metal"
  },
  {
    "id": 3,
    "music":"orchestral"
  },
  {
    "id": 3,
    "music":"jazz"
  },
  {
    "id": 3,
    "music":"percussion"
  }  
];

我想要实现的最终结果是基于上述数据的对象的以下结果数组,其中食物和音乐都是对象内的数组。

我知道我可以使用简单的数组迭代来实现以下结果,但我想看看是否可以使用 JavaScript filterreduce 以更好的方式完成>.

dets 数组是父数组,使用“id”值检索foodsmusics 中的子数组值。

let result = [
  {
    "id": 1,
    "name":"tom",
    "country":"USA",
    "phone": "1234",
    "foods": ["pizza","pasta","oranges"],
    "musics": ["jazz","funk","country"]
  },
  {
    "id": 2,
    "name":"sarah",
    "country":"ITALY",
    "phone": "8899",
    "foods": ["donuts","pizza","apples"],
    "musics": ["jazz","rock","heavy metal"]
  },
  {
    "id": 3,
    "name":"harry",
    "country":"GERMANY",
    "phone": "3434",
    "foods": ["apples","strawberries"],
    "musics": ["orchestral","jazz","percussion"]    
  }
];

【问题讨论】:

  • "更好的方法" ...好吧,那就不要使用 reduce :)
  • 如果一个 id 没有出现在任何数组中怎么办?
  • “id”将始终存在于数组中,并始终在寻找新的方法。

标签: javascript arrays json ecmascript-6


【解决方案1】:

您可以使用map 循环通过dets 数组。可以使用reduce获取id对应的音乐和美食。 (您可以使用filter,但这需要另一个循环来获取名称/音乐属性)。

您可以使用扩展运算符对原始对象进行浅拷贝。

let dets = [{"id":1,"name":"tom","country":"USA","phone":"1234"},{"id":2,"name":"sarah","country":"ITALY","phone":"8899"},{"id":3,"name":"harry","country":"GERMANY","phone":"3434"}];
let foods = [{"id":1,"name":"pizza"},{"id":1,"name":"pasta"},{"id":1,"name":"oranges"},{"id":2,"name":"donuts"},{"id":2,"name":"pizza"},{"id":2,"name":"apples"},{"id":3,"name":"apples"},{"id":3,"name":"strawberries"}];
let musics = [{"id":1,"music":"jazz"},{"id":1,"music":"funk"},{"id":1,"music":"country"},{"id":2,"music":"jazz"},{"id":2,"music":"rock"},{"id":2,"music":"heavy metal"},{"id":3,"music":"orchestral"},{"id":3,"music":"jazz"},{"id":3,"music":"percussion"}];

let result = dets.map(o => {
  return {
    ...o,
    foods: foods.reduce((c, v) => v.id === o.id ? c.concat(v.name) : c, []),
    musics: musics.reduce((c, v) => v.id === o.id ? c.concat(v.music) : c, []),
  }
});

console.log(result);

另一种选择是设置食物和音乐地图变量。这是为了减少循环。

let dets = [{"id":1,"name":"tom","country":"USA","phone":"1234"},{"id":2,"name":"sarah","country":"ITALY","phone":"8899"},{"id":3,"name":"harry","country":"GERMANY","phone":"3434"}];
let foods = [{"id":1,"name":"pizza"},{"id":1,"name":"pasta"},{"id":1,"name":"oranges"},{"id":2,"name":"donuts"},{"id":2,"name":"pizza"},{"id":2,"name":"apples"},{"id":3,"name":"apples"},{"id":3,"name":"strawberries"}];
let musics = [{"id":1,"music":"jazz"},{"id":1,"music":"funk"},{"id":1,"music":"country"},{"id":2,"music":"jazz"},{"id":2,"music":"rock"},{"id":2,"music":"heavy metal"},{"id":3,"music":"orchestral"},{"id":3,"music":"jazz"},{"id":3,"music":"percussion"}];

//Summarize the foods and music first
let foodsMap = foods.reduce((c, v) => (c[v.id] = (c[v.id] || []).concat(v.name), c), {});
let musicsMap = musics.reduce((c, v) => (c[v.id] = (c[v.id] || []).concat(v.music), c), {});

let result = dets.map(o => {
  return {
    ...o,
    foods: foodsMap[o.id] || [],
    musics: musicsMap[o.id] || [],
  }
});


console.log(result);

【讨论】:

    【解决方案2】:

        let dets = [{"id": 1,"name":"tom","country":"USA","phone": "1234"}, 
        {"id": 2,"name":"sarah","country":"ITALY","phone": "8899"},
        {"id": 3,"name":"harry","country":"GERMANY","phone": "3434"}];
        let foods = [{"id": 1,"name":"pizza"},
        {"id": 1,"name":"pasta"},
        {"id": 1,"name":"oranges"},  
        {"id": 2,"name":"donuts"},  
        {"id": 2,"name":"pizza"},
        {"id": 2,"name":"apples"},
        {"id": 3,"name":"apples"},
        {"id": 3,"name":"strawberries"}];
        let musics = [{"id": 1,"music":"jazz"},
        {"id": 1,"music":"funk"},
        {"id": 1,"music":"country"},  
        {"id": 2,"music":"jazz"},  
        {"id": 2,"music":"rock"},
        {"id": 2,"music":"heavy metal"},
        {"id": 3,"music":"orchestral"},
        {"id": 3,"music":"jazz"},
        {"id": 3,"music":"percussion"}];
        let output = dets.map((det)=>{
            det.foods = foods.filter((food)=>{
                return det.id === food.id;
            }).map((food)=>{
            return food.name;
            });
            det.musics = musics.filter((music)=>{
                return music.id === det.id;
            }).map((music)=>{
            return music.music;
            });
            return det;
        });
        console.log(output);

    【讨论】:

      【解决方案3】:

      您可以使用 id 来对象 Map 并用所有值填充它:

        const idMap = new Map();
        const get = id => idMap.get(id) || (obj => (idMap.set(id, obj), obj))({});
      
        for(const info of dets)
          Object.assign(get(info.id), info);
      
       for(const { food, id } of foods) {
          const user = get(id);
          (user.foods || (user.foods = []).push(food);
       }
      
        //...
      
        const result = [...idMap.values()];
      

      【讨论】:

        猜你喜欢
        • 2020-02-15
        • 2022-09-23
        • 2019-06-14
        • 1970-01-01
        • 1970-01-01
        • 2019-04-04
        • 1970-01-01
        • 2019-10-28
        • 1970-01-01
        相关资源
        最近更新 更多