下面给出的max
函数返回列表的最后一个元素的最后一个值,而不是最大值(我为调试目的添加了一些额外的println
)
def max(xs: List[Int]): Int = {
def loop(largest: Int, ys: List[Int]): Int = {
println("ys: " + ys)
println("largest: " + largest)
if(!ys.isEmpty) {
println("ys.head: " + ys.head + "\n")
if (largest >= ys.head)
loop(largest, ys.tail)
else ys.head
loop(ys.head, ys.tail)
}
else largest
}
loop(xs.head, xs.tail)
}
scala> max(List(1,2,3,1,2))
ys: List(2, 3, 1, 2)
largest: 1
ys.head: 2
ys: List(3, 1, 2)
largest: 2
ys.head: 3
ys: List(1, 2)
largest: 3
ys.head: 1
ys: List(2)
largest: 3
ys.head: 2
ys: List()
largest: 3 // shouldn't it just end here?
ys: List()
largest: 2
ys: List(2)
largest: 1
ys.head: 2
ys: List()
largest: 2
res0: Int = 2
答案 0 :(得分:2)
您的if
表达式应为:
if (largest >= ys.head)
loop(largest, ys.tail)
else
loop(ys.head, ys.tail)
您的代码目前与以下内容相同:
val result = if (largest >= ys.head)
loop(largest, ys.tail)
else ys.head
loop(ys.head, ys.tail)
所以你丢弃了递归调用的结果,然后返回loop(ys.head, ys.tail)
。
答案 1 :(得分:2)
仔细看看else
部分的外观:
else ys.head
loop(ys.head, ys.tail)
它没有多大意义:)这个应该是正确的:
else loop(ys.head, ys.tail)
但在这种情况下,我宁愿使用模式匹配:
def max(xs: List[Int]): Int = {
def loop(largest: Int, ys: List[Int]): Int = ys match {
case y :: rest if y > largest => loop(y, rest)
case y :: rest => loop(largest, rest)
case _ => largest
}
loop(xs.head, xs.tail)
}
我发现它更易于阅读和分析,并且(可以说)它会使得更难以犯这种错误
答案 2 :(得分:0)
获取列表最大值的众多方法之一依赖于对列表进行排序,然后获取第一个(或最后一个)元素;例如
def max(xs: List[Int]): Int = (xs sortWith {_>_}) (0)
在此函数中,sortWith
可以替换为对QuickSort实现的调用。
查看https://jazzy.id.au/default/2012/10/16/benchmarking_scala_against_java.html,了解QuickSort的非惯用Scala实现,并针对Java和惯用方法进行基准测试。