使用Reduce而不是链接Filter和Map

时间:2019-08-28 23:50:50

标签: javascript reduce

我有一个函数,它接收一个狗对象数组,并返回所有所有者名称的数组。

    dogs = [
      {name: 'Archie', breed: 'Lurcher', owner: 'Jack'},
      {name: 'Charlie', breed: 'Pug', owner: 'John'},
      {name: 'Buddy', breed: 'Pug', owner: 'Mike'}
    ]

我通过链接过滤器和映射获得结果,但这意味着我在同一列表上循环了两次。我知道这可以使用Reduce来完成,但不确定如何实现。在reduce上的很多例子似乎都是关于数字的,这在尝试解决我的问题时有点令人困惑。

任何帮助将不胜感激。谢谢

function getOwners(dogs) {

   return dogs.filter(dog => dog.breed === 'Pug').map(dog => dog.owner);
}

  returns ['John', 'Mike']

2 个答案:

答案 0 :(得分:3)

您要寻找的功能是:

dogs.reduce((total, current) => current.breed === "Pug" ? [...total, current.owner] : total, []);

我们遍历狗并为每个元素测试current.breed === "Pug",如果为真,则将当前狗的所有者添加到total数组中,否则我们将总数组保持原样。

答案 1 :(得分:0)

您传递一个初始数组,并且在减小值的同时仅推送未映射值的映射值。

const filteredMap = (filter, mapping) => {
  return arr => Array.prototype.reduce.call(arr, (accumulator, value) => {
    if (filter(value)) accumulator.push(mapping(value));
    return accumulator;
  }, []);
};

const getOwners = filteredMap(dog => dog.breed == 'Pug', dog => dog.owner);

getOwners([
  {name: 'Archie', breed: 'Lurcher', owner: 'Jack'},
  {name: 'Charlie', breed: 'Pug', owner: 'John'},
  {name: 'Buddy', breed: 'Pug', owner: 'Mike'}
]);  // => [ 'John', 'Mike' ]

将它写成循环可能更清楚:

const filteredMap = (filter, mapping) => {
  return arr => {
    const res = [];
    for (const value of arr) {
        if (filter(value)) res.push(mapping(value));
    }
    return res;
  };
};