热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

array.reduce_Array.reduce()方法的超能力

array.reduceECMAScript5在2009年引入了许多很棒的功能,其中大多数是数组方法,例如isArray,forEach&

array.reduce

ECMAScript 5在2009年引入了许多很棒的功能 ,其中大多数是数组方法,例如isArray , forEach , map , filter , every , some 。 但是,让我们谈谈我最喜欢的一个: reduce

reduce方法

reduce方法在数组的每个元素上执行reducer回调函数(由用户提供),从而产生单个输出值。

减速器

reducer函数采用四个参数:

  • 累加器(acc)
  • 当前值(当前)
  • 当前索引(idx)
  • 源数组(src)

reducer函数的返回值分配给累加器,累加器的值在整个数组的每次迭代中都会被记住,并最终成为最终的单个结果值。

重要提示:在每次迭代中,您必须   返回下一次迭代的累加器值(最终将是最终的返回值),否则累加器的下一个(最终是最终的)值将undefined

初始值

reduce方法采用第二个可选参数: initialValue
如果未提供,则累加器的初始值将是数组的第一个元素,并且第一次迭代将指向第二个元素。 如果initialValue   提供时,它将是累加器的初始值,并且第一次迭代将指向数组的第一个元素。

例子

有或没有初始值的数字求和

const numbers = [ 1 , 2 , 3 ];// Without initialValue
const sum = numbers.reduce(( accumulator, currentValue ) => accumulator + currentValue
);// Prints 6
console .log(sum);// With initialValue
const initialValue = 3 ;
const sumWithInitialValue = numbers.reduce(( accumulator, currentValue ) => accumulator + currentValue
, initialValue);// Prints 9
console .log(sumWithInitialValue);

如果没有初始值,则第一次迭代将使accumulator指向数组的第一个元素(1),而currentValue指向数组的第二个元素(2)。

给定初始值,第一次迭代将具有一个具有给定初始值(3)的值的accumulator ,而currentValue将指向数组的第一个元素(1)。

计算数组中的出现次数

让我们计算以下单词的出现次数,并将结果存储在地图中:

土拨鼠卡盘要多少木头
如果土拨鼠能夹木头?
他会努力,他会尽可能
和土拨鼠一样多
如果土拨鼠可以夹木头。

const sentence = "how much wood would a woodchuck chuck" +"if a woodchuck could chuck wood " +"he would chuck he would as much as he could " +"and chuck as much as a woodchuck would " +"if a woodchuck could chuck wood" ;const words = sentence.split( " " );const occurencesMap = words.reduce(( occurences, word ) => {const numOfOccurences = (occurences.get(word) || 0 ) + 1 ;occurences.set(word, numOfOccurences);return occurences;}
, new Map ());const numOfWoodchucks = occurencesMap.get( "woodchuck" );// 4
console .log(numOfWoodchucks);

我们初始化一个空的映射并将其用作累加器的初始值,在迭代句子中的单词时初始化或更新每个单词的出现次数。

这只是两个例子,但是现在您必须已经意识到reduce是多么的出色,对吗?

它允许您采用数组并将其值减小为基本上可以从其保存的数据派生的任何值。 它还允许您返回任何类型的数据,而与数组元素的类型无关。

一种统治所有人的方法?

回顾其他ES5数组方法,我们可以看到每个方法在数组上使用给定的回调函数并返回某种结果。

例如:

  • map转换数组的每个元素,并返回一个新的   数组。
  • every检查给定条件是否适用于数组中的每个元素,并返回相应的布尔值。

看起来很熟悉吧?

使用我们已经知道的知识,让我们尝试使用reduce来实现其他ES5数组方法。

注意:在每个示例中,我们都会将新方法添加到Array的原型中, this将指向我们正在操作的数组。

地图

map()方法创建一个新数组,其中每个原始元素都由给定的transformer回调进行transformer

用法

const array = [ 1 , 2 , 3 ];
const doubled = array.map( num => num * 2 );// Prints [2, 4, 6]
console .log(doubled);

使用将数组中每个数字加倍的转换器回调,我们得到一个新数组,其中每个元素都是其原始值的两倍。

reduce

map在一个数组map操作并返回一个新数组,因此累加器必须是一个数组。

Array .prototype.mapWithReduce = function ( transformer ) {return this .reduce( ( newArray, currentElement ) => {const newElement = transformer(currentElement);newArray.push(newElement);return newArray;}, []);
}const array = [ 1 , 2 , 3 ];
const doubled = array.mapWithReduce( num => num * 2 );// Prints [2, 4, 6]
console .log(doubled);

使用reduce ,我们从一个空的数组累加器开始,然后遍历该数组。 然后,我们将转换器回调应用于每个元素,并将其推入累加数组。

过滤

filter()方法创建一个新数组   通过提供的功能实现的所有通过测试的元素。

用法

const array = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ];
const evenOnly = array.filter( num => num % 2 === 0 );// Prints [2, 4, 6, 8, 10]
console .log(evenOnly);

使用测试回调过滤掉所有奇数,我们得到一个包含原始数组所有偶数元素的新数组。

reduce

就像前面的示例一样,filter也在数组上操作并返回一个新数组,因此累加器必须是数组。

Array .prototype.filterWithReduce = function ( tester ) {return this .reduce( ( newArray, currentElement ) => {if (tester(currentElement)) {newArray.push(currentElement);};return newArray;}, []);
}const array = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ];
const evenOnly = array.filterWithReduce( num => num % 2 === 0 );// Prints [2, 4, 6, 8, 10]
console .log(evenOnly);

使用reduce ,我们从一个空的数组累加器开始,然后遍历该数组。 然后,我们使用测试器回调检查是否应将每个元素都推到累积数组中。

每一个

every()方法测试数组中的所有元素是否通过提供的函数实现的测试。 它返回一个布尔值。

用法

const array = [ 1 , 2 , 3 , 4 , 5 ];
const result &#61; array.every( num &#61;> num <10 );// Prints true
console .log(result);

使用回调函数测试数组中的每个元素&#xff0c;我们得到一个布尔值&#xff0c;指示所有元素是否通过测试。 在这种情况下&#xff0c;所有元素都小于10&#xff0c;因此every元素都返回true

reduce

every运算符都对数组进行运算并返回布尔值&#xff0c;因此累加器必须为布尔值。

Array .prototype.everyWithReduce &#61; function ( tester ) {return this .reduce( ( acc, currentElement ) &#61;>acc && tester(currentElement), true );
}const array &#61; [ 1 , 2 , 3 , 4 , 5 ];
const result &#61; array.everyWithReduce( num &#61;> num <10 );// Prints true
console .log(result);

使用reduce &#xff0c;我们从布尔累加器值为true &#xff08;稍后将讨论原因&#xff09;并遍历数组。 然后&#xff0c;我们使用逻辑AND&#xff08; && &#xff09;将测试器回调的结果链接到累加器&#xff0c;以在所有元素均通过测试时最终返回true &#xff0c; otherwise返回false。

为什么从true开始&#xff1f;

如果数组为空&#xff0c;则无论测试回调如何&#xff0c; every返回true &#xff08;即使该回调返回false &#xff09;。

否则&#xff0c;如果所有元素都满足条件&#xff0c;则使用逻辑AND链接初始true值最终将解析为true 。 否则&#xff0c;链接最终将解析为false

一些

some&#xff08;&#xff09;方法测试数组中的至少一个元素是否通过了由提供的函数实现的测试。 它返回一个布尔值。

用法

const array &#61; [ 1 , 2 , 3 , 4 , 5 ];
const result &#61; array.some( num &#61;> num > 3 );// Prints true
console .log(result);

使用回调函数测试数组中的每个元素&#xff0c;我们得到一个布尔值&#xff0c;指示是否有任何元素通过测试。 在这种情况下&#xff0c;第四个元素大于3&#xff0c;因此some元素返回true

reduce

some对数组进行运算并返回布尔值&#xff0c;因此累加器必须为布尔值。

Array .prototype.someWithReduce &#61; function ( tester ) {return this .reduce( ( acc, currentElement ) &#61;>acc || tester(currentElement), false );
}const array &#61; [ 1 , 2 , 3 , 4 , 5 ];
const result &#61; array.someWithReduce( num &#61;> num > 3 );// Prints true
console .log(result);

使用reduce &#xff0c;我们从布尔累加器值false &#xff08;稍后将讨论原因&#xff09;&#xff0c;然后遍历数组。 然后&#xff0c;我们使用逻辑OR&#xff08; || &#xff09;将测试器回调的结果链接到累加器&#xff0c;以在任何元素通过测试时最终返回true &#xff0c;否则返回false

为什么从false开始&#xff1f;

如果数组为空&#xff0c;则无论测试回调如何&#xff0c;即使返回回调true &#xff0c; some返回false

否则&#xff0c;如果任何元素满足条件&#xff0c;则使用逻辑OR链接初始false值最终将解析为true 。 否则&#xff0c;链接最终将解析为false

免责声明&#xff08;每部分&#xff09;

every方法都会对数组中存在的每个元素执行一次提供的回调函数&#xff0c;直到找到回调返回虚假值&#xff08;转换为布尔值时该值为false &#xff09;的那个函数为止。 如果找到这样的元素&#xff0c;则every元素立即返回false

类似地&#xff0c; some &#xff0c;直到它找到地方回调返回truthy值&#xff08;即变成值的一个方法执行一次为每个存在于阵列中元件的回调函数true时转换成布尔&#xff09;。 如果找到了这样的元素&#xff0c;则some元素会立即返回true

但是&#xff0c;没有终止 reduce漂亮方法 中间循环 。
这意味着虽然两个实现&#xff08;原始的every/some方法以及使用reduce的相应实现&#xff09;的运行时均为O(n) &#xff0c;但原始实现很可能会终止而无需遍历整个数组&#xff0c;从而使它们更有效。

筛选器&#43;地图

给定一个数字数组&#xff0c;最有效的方法是过滤出所有偶数元素并将其余的元素平方&#xff08;使用ES5方法&#xff09;&#xff1f;

让我们先尝试filter然后再尝试map &#xff1a;

const array &#61; [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ];const tester &#61; num &#61;> num % 2 &#61;&#61;&#61; 1 ;
const transformer &#61; num &#61;> num * num;const result &#61; array.filter(tester).map(transformer);// Prints [1, 9, 25, 49, 81]
console .log(result);

我们创建一个仅保留奇数元素的测试器函数和一个将给定元素平方的变压器函数。 然后在链接filtermap方法时使用这两个回调函数&#xff0c;并返回所需的数组。

让我们用我们了解的通过reduce实现filtermap &#xff0c;只有这次我们将它们一次组合起来。

const array &#61; [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 ];const tester &#61; num &#61;> num % 2 &#61;&#61;&#61; 1 ;
const transformer &#61; num &#61;> num * num;const result &#61; array.reduce( ( newArray, currentElement ) &#61;> {if (tester(currentElement)) {const newElement &#61; transformer(currentElement);newArray.push(newElement); }return newArray;
}, []);// Prints [1, 9, 25, 49, 81]
console .log(result);

我们使用相同的测试器和转换器函数来测试每个元素是否应保留在数组中&#xff0c;并对其进行转换。

这种方法省去了创建过滤值中间数组的需要&#xff0c;并且由于不必迭代两个不同的数组&#xff08;原始数组和中间数组&#xff09;&#xff0c;我们得到了一种效率更高的算法。

结论

这些是如何使用功能强大的reduce方法实现其他ES5方法的一些示例。

您如何在日常编码中使用它&#xff1f; 分享评论&#xff01;

资料来源
  • w3schools的ES5功能
  • MDN Web文档提供的Javascript数组方法 。
    本文中的每个方法文档均来自此处。

翻译自: https://hackernoon.com/the-superpowers-of-arrayreduce-jn1536p6

array.reduce



推荐阅读
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • 本文介绍了机器学习手册中关于日期和时区操作的重要性以及其在实际应用中的作用。文章以一个故事为背景,描述了学童们面对老先生的教导时的反应,以及上官如在这个过程中的表现。同时,文章也提到了顾慎为对上官如的恨意以及他们之间的矛盾源于早年的结局。最后,文章强调了日期和时区操作在机器学习中的重要性,并指出了其在实际应用中的作用和意义。 ... [详细]
  • 本文介绍了在wepy中运用小顺序页面受权的计划,包含了用户点击作废后的从新受权计划。 ... [详细]
  • Java序列化对象传给PHP的方法及原理解析
    本文介绍了Java序列化对象传给PHP的方法及原理,包括Java对象传递的方式、序列化的方式、PHP中的序列化用法介绍、Java是否能反序列化PHP的数据、Java序列化的原理以及解决Java序列化中的问题。同时还解释了序列化的概念和作用,以及代码执行序列化所需要的权限。最后指出,序列化会将对象实例的所有字段都进行序列化,使得数据能够被表示为实例的序列化数据,但只有能够解释该格式的代码才能够确定数据的内容。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 如何用UE4制作2D游戏文档——计算篇
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了如何用UE4制作2D游戏文档——计算篇相关的知识,希望对你有一定的参考价值。 ... [详细]
  • C# 7.0 新特性:基于Tuple的“多”返回值方法
    本文介绍了C# 7.0中基于Tuple的“多”返回值方法的使用。通过对C# 6.0及更早版本的做法进行回顾,提出了问题:如何使一个方法可返回多个返回值。然后详细介绍了C# 7.0中使用Tuple的写法,并给出了示例代码。最后,总结了该新特性的优点。 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 判断数组是否全为0_连续子数组的最大和的解题思路及代码方法一_动态规划
    本文介绍了判断数组是否全为0以及求解连续子数组的最大和的解题思路及代码方法一,即动态规划。通过动态规划的方法,可以找出连续子数组的最大和,具体思路是尽量选择正数的部分,遇到负数则不选择进去,遇到正数则保留并继续考察。本文给出了状态定义和状态转移方程,并提供了具体的代码实现。 ... [详细]
  • 本文介绍了一个在线急等问题解决方法,即如何统计数据库中某个字段下的所有数据,并将结果显示在文本框里。作者提到了自己是一个菜鸟,希望能够得到帮助。作者使用的是ACCESS数据库,并且给出了一个例子,希望得到的结果是560。作者还提到自己已经尝试了使用"select sum(字段2) from 表名"的语句,得到的结果是650,但不知道如何得到560。希望能够得到解决方案。 ... [详细]
  • 本文介绍了在使用vue和webpack进行异步组件按需加载时可能出现的报错问题,并提供了解决方法。同时还解答了关于局部注册组件和v-if指令的相关问题。 ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
author-avatar
技术小白
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有