我试图找到一系列行中最长行的长度。
val lines = Source.fromFile(args(0)).getLines() //a collection of strings
val longestLine = lines.reduceLeft( (a,b) =>
if(a.length > b.length) a.length else b.length )
但是这会导致以下错误:
/home/jesvin/dev/scala/readfile.scala:11: error: type mismatch;
found : Int
required: String
if(a.length > b.length) a.length else b.length )
^
/home/jesvin/dev/scala/readfile.scala:11: error: type mismatch;
found : Int
required: String
if(a.length > b.length) a.length else b.length )
^
two errors found
我在某些位置尝试了一些显式的返回语句和类型转换,但它没有用。
我使用reduceLeft
错了吗?
答案 0 :(得分:11)
我使用
reduceLeft
错了吗?
是的,您想拥有fold
而不是reduce
的行为。 reduce
生成的类型与集合的类型参数相同 - 它是fold
,可以生成另一种类型。
scala> Seq("a","b","cd").reduceLeft(_+_)
res24: String = abcd
这里,Seq的类型参数是String - 因此reduceLeft
也生成一个String。
scala> Seq("a","b","cd").foldLeft(0)(_+_.length)
res25: Int = 4
相比之下,foldLeft
可以生成另一种类型 - 在本例中为Int。
在您的示例中seq.max
是您想要的。尝试自己实现它,然后在查看源代码时验证您的实现是否正确。
提示:reduce
是fold
,其实现方式如下:
def reduce(f: (A, A) => A) =
tail.fold(head)(f)
这就是reduce
在调用空集合时抛出异常的原因。
答案 1 :(得分:3)
是的,你是。 reduceLeft必须返回与集合中的对象类型兼容的对象 - 在本例中为String。请参阅Programming in Scala以了解完全您的问题 - 直到相同的变量名称。
你想:
val longestLine
= lines.reduceLeft( (a,b) => if(a.length > b.length) a else b ).length
当然,这仅在集合非空时才有效。出于这个原因,和其他人一样,foldLeft通常更可取,如@Antoras所示。