当前位置: 首页 > 后端技术 > Node.js

我是怎样用函数式JavaScript计算数组平均值的

时间:2023-04-03 16:40:57 Node.js

如何使用函数式JavaScript计算数组的平均值?原文:FUNCTIONALJAVASCRIPT:FIVEWAYSTOCACULATEANAVERAGEWITHARRAYREDUCE译者:Fundebug函数式编程。因为它们真的很普通而且超级简单。.map()和.filter()都只需要一个参数,它定义了对数组的每个元素进行操作的函数。reduce()有点复杂。我之前写过一篇文章,讲为什么人们很难掌握reduce()方法。原因之一是许多介绍材料仅使用算术作为示例。我已经写了很多使用reduce()来处理算术以外的事情的例子。使用reduce()计算数组的平均值是一种常见的模式。代码看起来很简单,但是在计算最终结果之前需要做两个准备:数组的长度和数组中所有元素的总和。这两件事看起来很简单,所以计算数组的平均值并不难。.解决方案如下:functionaverage(nums){returnnums.reduce((a,b)=>a+b)/nums.length;}没那么难吧?但是如果数据结构变得复杂,就不是那么简单了。比如数组中的元素是对象,需要先过滤掉一些对象,然后从对象中获取数字。这种情况会使计算平均值变得有点复杂。接下来我们解决一个类似的问题(受到这个FreeCodeCamp挑战的启发),我们提供了5种不同的解决方案,每一种都有自己的优点和缺点。这5个方法也展示了JavaScript的灵活性。希望能给大家一些在实践中使用reduce的启发。问题提出假设我们有一系列维多利亚时代的常用口语。接下来我们需要找到仍然存在于Google图书中的单词并计算它们的平均流行度。数据的格式是这样的:constvictorianSlang=[{term:"doingthebear",found:true,popularity:108},{term:"katterzem",found:false,popularity:null},{term:"boneshaker",found:true,popularity:609},{term:"smotheringaparrot",found:false,popularity:null},{term:"damfino",found:true,popularity:232},{term:"rainnapper",found:false,popularity:null},{term:"donkey'sbreakfast",found:true,popularity:787},{term:"rationalcostume",found:true,popularity:513},{term:真,popularity:513},{term:“介意油脂”,发现:真实,受欢迎程度:154}];接下来我们使用5种不同的方法来计算平均流行度值。1.for循环先试一下,我们不用reduce()。如果您不熟悉常见的数组函数,使用for循环会让您更好地理解我们要做什么。letpopularitySum=0;letitemsFound=0;constlen=victorianSlang.length;letitem=null;for(leti=0;ia=>a。过滤器(p);constmap=f=>a=>a.map(f);constprop=k=>x=>x[k];constreduce=r=>i=>a=>a.reduce(r,i);constcompose=(...fns)=>arg=>fns.reduceRight((arg,fn)=>fn(arg),arg);//blackbird组合器。//请参阅:https://jrsinclair。com/articles/2019/compose-js-functions-multiple-parameters/constB1=f=>g=>h=>x=>f(g(x))(h(x));//计算//---------------------------------------------------//Sum函数constsum=reduce((a,i)=>a+i)(0);//计算数组长度的函数constlength=a=>a.length;//除法函数constdiv=a=>b=>a/b;//我们使用compose()来组合函数//compose()可以倒着读参数来理解程序的含义constcalcPopularity=compose(B1(div)(sum)(length),map(prop("popularity")),过滤器(prop("找到")));constaveragePopularity=calcPopularity(维多利亚俚语);控制台。log("平均人气:",averagePopularity);我们在compose中从后往前进行所有的计算,首先filter(prop('found'))过滤掉GoogleBooks中的所有词条,然后通过map(prop('popularity'))得到所有的popularity值,最后使用神奇的黑鸟(B1)组合器计算相同输入的总和和长度并得到平均值。//以下所有行都是等价的:constavg1=B1(div)(sum)(length);constavg2=arr=>div(sum(arr))(长度(arr));constavg3=arr=>总和(arr)/长度(arr);constavg4=arr=>arr.reduce((a,x)=>a+x,0)/arr.length;看不懂也不用着急,以上主要是给大家演示4种实现平均功能的方法。这就是JavaScript的美妙之处。相对而言,这篇文章的内容有点极客。虽然笔者之前深入使用函数式语言Haskell做过很多研究项目,对函数式语言有很好的理解,但是我们不建议在实际项目中使用point-free风格的代码,维护成本会很高。我们Fundebug的所有代码都要求直观易懂,不建议使用一些稀奇古怪的技巧来实现。除非有一些不得已的地方,注释一定要写的很清楚,减少后期的维护成本。5.终极优化:所有解都运行良好,直到结果计算一次。那些使用reduce()的解决方案有一个共同点。他们将大问题分解为小的子问题,然后以不同的方式将它们组合起来。但是也要注意,他们遍历了数组3次,感觉效率很低。如果能计算一次,就是最好的解决方案。是的,确实如此,但这需要一点数学知识。计算n个元素的均值,我们用下面的公式:那么,计算n+1个元素的均值,用同样的公式(唯一不同的是n变成了n+1):等价于:asYu:做一些改造:结论是我们总可以记录当前状态下所有满足条件的元素的平均值。只要我们知道前面所有元素的平均值和元素个数就可以了。//平均函数averageScores({avg,n},slangTermInfo){if(!slangTermInfo.found){return{avg,n};}return{avg:(slangTermInfo.popularity+n*avg)/(n+1),n:n+1};}constinitialVals={avg:0,n:0};constaveragePopularity=victorianSlang.reduce(averageScores,initialVals).avg;console.log("平均人气:",averagePopularity);该方法只需要遍历一次计算平均值即可。缺点是我们做了更多的计算。每当一个元素满足条件时,必须进行乘法和除法,而不是最后一次除法。但是,它使用的内存较少,因为没有中间数组变量,我们只是记录一个只有两个元素的对象。这样写还有一个缺点,代码一点都不直观,后续维护也麻烦。至少乍一看是不可能理解它的作用的。那么,哪种解决方案最好?这取决于。也许你有一个大数组要处理,也许你的代码需要在内存很少的硬件上运行。在这些情况下,选项5效果最好。如果性能不是问题,那么即使是效率最低的方法也可以。您需要选择最合适的。也有一些聪明的朋友会想:是否可以把问题拆解成子问题,仍然只遍历一次?是的,有。需要换能器。关于FundebugFundebug专注于JavaScript、微信小程序、微信小游戏、支付宝小程序、ReactNative、Node.js和Java在线应用的实时BUG监控。自2016年双十一正式上线以来,Fundebug累计处理了10亿+错误事件,其付费客户包括谷歌、360、金山、人民网等众多品牌公司。欢迎大家免费试用!转载版权声明请注明作者Fundebug及本文地址:https://blog.fundebug.com/2019/06/05/5-ways-calculate-an-average-with-reduce/