You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala中如何用函数式方法计算点列表的周长?

嘿,我来帮你解决这个Scala的类型不匹配问题!

首先得搞清楚为啥你用reduceLeft(euclideanDist)会报错:reduceLeft的工作逻辑是,拿前一次运算的结果和下一个列表元素继续执行传入的函数。第一次调用euclideanDist会得到一个Double值,但下一次它就会尝试把这个Double和下一个List[Double]传给euclideanDist——可你的函数只接受两个List[Double]参数啊!这就直接触发了类型不匹配的编译错误。

不用命令式循环,咱们用Scala地道的函数式写法来搞定,这里有两种靠谱的方案:

方案1:用sliding(2)生成连续点对

sliding(2)方法可以把你的点列表分割成连续的两两子序列,比如你的输入会被拆成(List(0,0), List(0,1))、(List(0,1), List(1,1))这样的点对,接着对每个点对计算距离,最后求和就行:

import scala.collection.mutable.ListBuffer
import math.{sqrt, pow}

// 你的欧氏距离函数保持不变
def euclideanDist(pt1: List[Double], pt2: List[Double]): Double = 
  sqrt(pow(pt1(0)-pt2(0), 2) + pow(pt1(1)-pt2(1), 2))

def perimeter(arr: ListBuffer[List[Double]]): Double = 
  arr.sliding(2)
    .map { case List(pt1, pt2) => euclideanDist(pt1, pt2) }
    .sum

测试一下你的示例输入:

val arr: ListBuffer[List[Double]] = ListBuffer(List(0, 0), List(0,1), List(1,1), List(1,0), List(0, 0))
perimeter(arr) // 输出 4.0,完全符合预期

方案2:用foldLeft追踪前一个点和总和

如果想更明确地控制遍历过程,可以用foldLeft来携带两个状态:遍历到当前的总和,以及前一个点。这样每次迭代都能计算当前点和前一个点的距离,并累加到总和里:

def perimeter(arr: ListBuffer[List[Double]]): Double = 
  arr.tail.foldLeft((arr.head, 0.0)) { case ((prevPt, total), currPt) =>
    (currPt, total + euclideanDist(prevPt, currPt))
  }._2

这里arr.tail从第二个点开始遍历,初始状态是(第一个点, 0.0),每次迭代更新当前点和总和,最后取出元组的第二个元素就是周长总和。

这两种写法都是纯函数式的,完全符合Scala的风格,而且完美解决了类型不匹配的问题~

内容的提问来源于stack exchange,提问作者Ébe Isaac

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:22:31