map(), reduce() and filter vs forEach()

map(), reduce() and filter vs forEach()

本文关键字:vs forEach filter reduce map and      更新时间:2023-09-26

我刚刚了解了MapReduce,所以我想知道写作是否有任何优势

const initialValue = 0;
if (this.items) {
  return this.items.filter(function (item) {
    return item && item.quantity && item.price;
  }).reduce(function(previousValue, currentValue) {
    return previousValue + currentValue.quantity * currentValue.price ;
  }, initialValue);
} else {
  return initialValue;
}

而不仅仅是

let total = 0;
if (this.items) {
  this.items.forEach(function(item) {
    if (item && item.quantity && item.price) {
      total += item.quantity * item.price;
    }
  });
}
return total;

对于未来的读者,有一些更惯用的方法可以用函数的方式编写缩减。通常使用它们,因为它们更清晰地传达意图(并且不会向范围添加变量)。

注意:我假设this.items有类型

({ quantity: number; price: number } | undefined)[] | undefined

但是每个示例都容忍比问题中的两个示例更多的无效数据。

减少前的过滤和映射

末尾的默认值

return this.items
    ?.filter(item => item?.quantity && item.price)
    .map(item => item.quantity * item.price)
    .reduce((a, b) => a + b, 0) ?? 0

开头的默认数组

return (this.items ?? [])
    .filter(item => item?.quantity && item.price)
    .map(item => item.quantity * item.price)
    .reduce((a, b) => a + b, 0)

处理地图中的过滤器

我不会仅仅因为前两个更清楚地传达意图而推荐这些。

末尾的默认值

return this.items
    ?.map(item => (item?.quantity ?? 0) * (item?.price ?? 0))
    .reduce((a, b) => a + b, 0) ?? 0

开头的默认数组

return (this.items ?? [])
    .map(item => (item?.quantity ?? 0) * (item?.price ?? 0))
    .reduce((a, b) => a + b, 0)

解构

前面的每个示例都可以通过解构来完成。我举一个例子。

return (this.items ?? [])
    .filter(item => item) // Ensure item exists; sufficient for the cases we need to worry about
    .map(({ price = 0, quantity = 0 }) => quantity * price)
    .reduce((a, b) => a + b, 0)

没有地图

我们现在可以在没有地图的情况下进行缩减。这也可以在不解构的情况下完成,但这似乎(对我来说)不优雅。

return (this.items ?? [])
    .filter(item => item)
    .reduce((sum, { price = 0, quantity = 0 }) => sum + quantity * price, 0)

当然,您可以更改筛选条件,这将我们带回问题中大致的第一个示例:

return (this.items ?? [])
    .filter(item => item?.price && item.quantity)
    .reduce((sum, { price, quantity }) => sum + quantity * price, 0)

原始forEach循环

其中一些更改也可以对原始循环进行:

let total = 0;
items?.forEach((item) => {
  if (item?.quantity && item.price) {
    total += item.quantity * item.price;
  }
});
return total;

我看不出第一个比第二个*有任何优势。然而,第二个甚至比第一个更快,看起来更干净!第一个的目的可能是演示内置数组函数的使用。

然而,mapreduce用于很多元素,所以你可以尽可能地加快它。这应该是你能得到的最快的:

const initialValue = 0;
let total = initialValue;
if (this.items) {
  for (var i = this.items.length; i--;) {
    let item = this.items[i]
    if (item && item.quantity && item.price) {
      total += item.quantity * item.price;
    }
  }
  return total;
} else {
  return initialValue 
}

此外,如果您知道数组是连续的,则可以将if放在循环中。这两个if都只是为了确保正确构建数组并且脚本不会遇到错误,这对于用户数据输入很有用,但在封闭系统中您不需要它们。


*我注意到,第二个缺少默认值return initialValue

让我们首先使用下面给出的代码来了解 forEach:

        let arr = [2,3,4,5,6];
        
        arr.forEach((value,index,array) => {
            console.log(value,index,array);
        })

在上面的代码中,我们使用了 for Each 循环,我们可以在其中给出值、索引、数组等参数——这将返回该值和完整数组的值和索引。

让我们了解地图中的地图,它将创建一个新数组并返回该数组

        let a = arr.map((value , index ,array)=>{
            console.log(value , index,array);
            return value + 1;
        })
        console.log(a);
In this you can return the values or change as per you preference like return value*10 or return value + 1;

让我们了解过滤器中的过滤器,它将创建一个新数组并返回该数组

        let arr2 = [42,3,1,45,5,55];
        
        let a2 = arr2.filter((value)=>{
        return value < 10;
        })
    
    console.log(a2);
In this we can give some condition like return value>10 or return value < 10 ans many more

在reduce方法中,它将通过计算函数返回单个值

        let arr3 = [1,2,3,5,2,1];
         
        let newarr3 = arr3.reduce((val1,val2) => {
        return val1+val2;
        })
        console.log(newarr3);

在上面的代码中,首先是 val1=1,val2=2,然后它们的总和为 3 而不是 val1=3,val2= 是 5,因此它将汇总数组中的所有元素并返回 ans 为 14。

重要 - 映射,过滤器,减少不会更改您现有的数组!!