我正处于scala的第二个晚上,我正在抵制用scala写东西的冲动,我曾经在java中做过这些,并试图学习所有的习语.在这种情况下,我希望只使用闭包,映射和列表理解这样的东西来计算平均值.无论这是否是计算平均值的最佳方法,我只想知道如何在scala中执行这些操作仅用于学习目的
这是一个例子:下面的平均方法几乎没有实现.我有几个其他的方法来查找个人用户ID给出的评级使用TraversableLike的查找方法(我认为),但没有更多的是scala特定的,真的.我如何计算给定List [RatingEvent]的平均值,其中RatingEvent.rating是一个双值,我将以类似scala的方式计算该List的所有值的平均值?
package com.brinksys.liftnex.model
class Movie(val id : Int, val ratingEvents : List[RatingEvent]) {
def getRatingByUser(userId : Int) : Int = {
return getRatingEventByUserId(userId).rating
}
def getRatingEventByUserId(userId : Int) : RatingEvent = {
var result = ratingEvents find {e => e.userId == userId }
return result.get
}
def average() : Double = {
/*
fill in the blanks where an average of all ratingEvent.rating values is expected
*/
return 3.8
}
}
Run Code Online (Sandbox Code Playgroud)
经验丰富的scala pro如何填充该方法并使用scala的功能使其尽可能简洁?我知道如何在java中这样做,这是我想要避免的.
如果我在python中这样做,我认为最pythonic的方式是:
sum([re.rating. for re in ratingEvents]) / len(ratingEvents)
Run Code Online (Sandbox Code Playgroud)
或者如果我强迫自己使用一个闭包(这是我至少想在scala中学习的东西):
reduce(lambda x, y : x + y, [re.rating for re in ratingEvents]) / len(ratingEvents)
Run Code Online (Sandbox Code Playgroud)
这是我想在scala中学习的这些类型的东西的用法.
你的建议?欢迎任何指向与此相关的优秀教程/参考资料:D
Rex*_*err 31
如果您要对事物进行数学运算,使用List并不总是最快的方法因为List不知道它有多长 - 所以ratingEvents.length需要时间与长度成正比.(不是很多时间,被授予,但它必须遍历整个列表来告诉.)但是如果你主要是操纵数据结构而只是偶尔需要计算总和或其他什么,所以它不是时间关键的核心你的代码,然后使用List是花花公子.
无论如何,这样做的规范方法是使用折叠来计算总和:
(0.0 /: ratingEvents){_ + _.rating} / ratingEvents.length
// Equivalently, though more verbosely:
// ratingEvents.foldLeft(0.0)(_ + _.rating) / ratingEvents.length
Run Code Online (Sandbox Code Playgroud)
或者通过映射然后求和(仅限2.8):
ratingEvents.map(_.rating).sum / ratingEvents.length
Run Code Online (Sandbox Code Playgroud)
有关地图和折叠的更多信息,请参阅有关该主题的此问题.
Lan*_*dei 11
你可以一次性计算总和和长度,但我怀疑这有助于除了很长的列表.它看起来像这样:
val (s,l) = ratingEvents.foldLeft((0.0, 0))((t, r)=>(t._1 + r.rating, t._2 + 1))
val avg = s / l
Run Code Online (Sandbox Code Playgroud)
我认为对于这个例子来说Rex的解决方案要好得多,但在其他用例中,"折叠过度元组技巧"可能是必不可少的.
由于mean和其他描述性统计数据类似standard deviation或median在不同的上下文中需要,您还可以使用一个小的可重用隐式帮助器类来允许更简化的链式命令:
implicit class ImplDoubleVecUtils(values: Seq[Double]) {
def mean = values.sum / values.length
}
val meanRating = ratingEvents.map(_.rating).mean
Run Code Online (Sandbox Code Playgroud)
甚至似乎可以为所有数字类型以通用方式编写此代码。