关于 Array.apply(null, { length:20 }).map() 的思考

本文深入探讨了函数式编程中的循环方法,特别是如何利用Array.apply和类数组特性优雅地实现循环,解决传统for循环的局限性,适用于Vue等前端开发场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

vuerender的文档中出现了,用来循环生成元素。

是什么

本质是函数式编程循环方法

就是一种循环方法,你用for循环代替,效果也是一样的,但是Array.apply(null, { length: 20 }).map()算是函数式编程

怎么实现函数式编程中的循环

如果不用for,你脑海中可能马上会想起reduceforEachmap这些迭代器函数,都能产生循环。比如:

[1,2,3].forEach((it,index)=>{
	console.log(index)   // 0 1 2
})

这就是简单的函数式循环。然而重点其实是前面需要循环的数组,如何优雅的产生。

如果我们想循环20次,直接写一个020的数组,结合forEach是可以的,但是未免显得有些拙略,

比如[1,2,3.....20].forEach(),如果要循环100次,那岂不是要写100个??

所以,可以使用js内置函数Array()来生成一个指定长度的数组,这样子只需要指定长度就能循环了

Array(20).forEach(()=>{
	// do something
})

直接使用Array()的问题

直接使用Array()可以生成指定长度的数组,但是会有一个问题:数组里面的值都是没有初始化的!!重要的是,你拿不到循环的索引,因为里面的keyvalue都是empty状态

Array(3).forEach((it,index)=>{
	console.log(index)  // undefiend
})
// 拿不到index,无法判断循环进度

引入apply

为了解决index无法获取的问题,我们可以Array()初始化的时候传入数值

Array.apply(null,[1,2,3]).forEach((it,index)=>{
	console.log(index)   // 1 2 3
})

其实就是执行Array函数,然后传入了参数1,2,3

索引问题就解决了,但是如果我要用apply循环100次呢?手写到100??继续往下

类数组

函数式循环最精巧的地方,应该就在于{ length: 20 }

apply函数传入的第二个参数,可以是类数组(敲黑板)!!什么是类数组?拥有length属性,同时存在key是数字的对象,就是类数组;比如我们用document.getElementsByClassName('div')获取的dom元素,含有lenth属性,同时可以通过下标0,1…获取元素,是类数组。

// 类数组
{length:2}

//等价于
{0:undefiend,1:undefiend,length:2}

{length:20}的类数组表示的是啥呢?

就是长度20的对象,每个对象的值都是undefined,所以Array.apply(null,{length:20}),实际上就是产生了一个长度为20具有初始值的数组。

如此,函数式循环实现,索引问题解决

话外

把问题的切入点转换成“函数式编程如何实现循环”,问题就容易解决多了。

可以看出vue文档的作者是函数式编程的爱好者,如果你跟他讲for循环,他可能会跟你急😅hahahaha。

现有udf val pearsonCorr = udf { (x: Seq[Double], y: Seq[Double]) => require(x.length == y.length, "数组长度必须相同") val n = x.length if (n <= 1) Double.NaN // 需要至少2个点计算相关性 else { val sumX = x.sum val sumY = y.sum val sumXY = (x zip y).map { case (a, b) => a * b }.sum val sumX2 = x.map(a => a * a).sum val sumY2 = y.map(b => b * b).sum val numerator = n * sumXY - sumX * sumY val denominator = math.sqrt(n * sumX2 - sumX * sumX) * math.sqrt(n * sumY2 - sumY * sumY) if (denominator == 0) Double.NaN else numerator / denominator } } 在dataworks上跑scala编写的spark任务,报错 2025-07-29 17:07:02,618 ERROR org.apache.spark.deploy.yarn.ApplicationMaster - User class threw exception: org.apache.spark.SparkException: Job aborted due to stage failure: Task 41 in stage 638.0 failed 4 times, most recent failure: Lost task 41.3 in stage 638.0 (TID 27945, 3010c5210.cloud.c8.am301, executor 12): org.apache.spark.SparkException: Failed to execute user defined function($anonfun$48: (array<double>, array<double>) => double) at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.processNext(Unknown Source) at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43) at org.apache.spark.sql.execution.WholeStageCodegenExec$$anonfun$10$$anon$1.hasNext(WholeStageCodegenExec.scala:614) at org.apache.spark.sql.execution.UnsafeExternalRowSorter.sort(UnsafeExternalRowSorter.java:216) at org.apache.spark.sql.execution.exchange.ShuffleExchangeExec$$anonfun$2.apply(ShuffleExchangeExec.scala:279) at org.apache.spark.sql.execution.exchange.ShuffleExchangeExec$$anonfun$2.apply(ShuffleExchangeExec.scala:250) at org.apache.spark.rdd.RDD$$anonfun$mapPartitionsInternal$1$$anonfun$apply$25.apply(RDD.scala:830) at org.apache.spark.rdd.RDD$$anonfun$mapPartitionsInternal$1$$anonfun$apply$25.apply(RDD.scala:830) at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38) at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:324) at org.apache.spark.rdd.RDD.iterator(RDD.scala:288) at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38) at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:324) at org.apache.spark.rdd.RDD.iterator(RDD.scala:288) at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:96) at org.apache.spark.scheduler.ShuffleMapTask.runTask(ShuffleMapTask.scala:53) at org.apache.spark.scheduler.Task.run(Task.scala:109) at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:345) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745) Caused by: java.lang.IllegalArgumentException: requirement failed: ???????? at scala.Predef$.require(Predef.scala:224) at com.bmsoft.operate.VsZUserOverlimitEventPeriodNew$$anonfun$48.apply(VsZUserOverlimitEventPeriodNew.scala:1894) at com.bmsoft.operate.VsZUserOverlimitEventPeriodNew$$anonfun$48.apply(VsZUserOverlimitEventPeriodNew.scala:1893) ... 21 more 怎么将udf方法改下
最新发布
07-30
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值