代码之家  ›  专栏  ›  技术社区  ›  whaley

Scala-计算平均值双重目标在列表中

  •  11
  • whaley  · 技术社区  · 14 年前

    我正在参加scala的第二个晚上,我抵制着用scala写东西的冲动,就像我以前用java写东西一样,努力学习所有的习惯用法。在本例中,我希望使用闭包、映射和列表理解等方法来计算平均值。不管这是否是计算平均值的最佳方法,我只想知道如何在scala中进行这些操作,仅用于学习目的

    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
        }
    }
    

    一个经验丰富的scala pro如何填充该方法并使用scala的特性使其尽可能简洁?我知道我将如何在java中实现它,这是我想要避免的。

    如果我是用python来做的,我认为最具python风格的方式应该是:

    sum([re.rating. for re in ratingEvents]) / len(ratingEvents)
    

    或者如果我强迫自己使用闭包(这是我至少想在scala中学习的东西):

    reduce(lambda x, y : x + y, [re.rating for re in ratingEvents]) / len(ratingEvents)
    

    我想在scala中学习这些类型的用法。

    4 回复  |  直到 9 年前
        1
  •  35
  •   Community CDub    7 年前

    如果你要做数学的话,用 List 并不总是最快的方式,因为 不知道要多久——所以 ratingEvents.length 时间与长度成正比。)不太好 许多的 时间,当然,但它必须遍历整个列表才能告诉你。)但是如果你主要是在操作数据结构,而且只是偶尔需要计算一个和或什么的,所以它不是你代码的时间关键核心,那么使用 列表 他是个花花公子。

    不管怎么说,标准的方法是通过折叠来计算总和:

    (0.0 /: ratingEvents){_ + _.rating} / ratingEvents.length
    
    // Equivalently, though more verbosely:
    // ratingEvents.foldLeft(0.0)(_ + _.rating) / ratingEvents.length
    

    ratingEvents.map(_.rating).sum / ratingEvents.length
    

    有关贴图和折叠的详细信息,请参见 this question on that topic .

        2
  •  12
  •   Landei    14 年前

    可以 一次性计算总和和长度,但我怀疑这是否有帮助,除了 非常 长长的名单。它看起来是这样的:

    val (s,l) = ratingEvents.foldLeft((0.0, 0))((t, r)=>(t._1 + r.rating, t._2 + 1)) 
    val avg = s / l
    

        3
  •  7
  •   Community CDub    7 年前

    mean 其他描述性统计如 standard deviation median 如果在不同的上下文中需要,您还可以使用一个小型的可重用隐式帮助器类来允许更精简的链式命令:

      implicit class ImplDoubleVecUtils(values: Seq[Double]) {
    
        def mean = values.sum / values.length
      }
    
      val meanRating = ratingEvents.map(_.rating).mean
    

    它甚至 seems to be

        4
  •  1
  •   vindev    6 年前

    我可以建议两种方法:

    def average(x: Array[Double]): Double = x.foldLeft(0.0)(_ + _) / x.length
    
    def average(x: Array[Double]): Double = x.sum / x.length