Calculating the Moving Average of a List

后端 未结 18 1115
悲哀的现实
悲哀的现实 2020-12-07 09:01

This weekend I decided to try my hand at some Scala and Clojure. I\'m proficient with object oriented programming, and so Scala was easy to pick up as a language, but wante

18条回答
  •  粉色の甜心
    2020-12-07 09:51

    This solution is in Haskell, which is more familiar to me:

    slidingSums :: Num t => Int -> [t] -> [t]
    slidingSums n list = case (splitAt (n - 1) list) of
                          (window, []) -> [] -- list contains less than n elements
                          (window, rest) -> slidingSums' list rest (sum window)
      where
        slidingSums' _ [] _ = []
        slidingSums' (hl : tl) (hr : tr) sumLastNm1 = sumLastN : slidingSums' tl tr (sumLastN - hl)
          where sumLastN = sumLastNm1 + hr
    
    movingAverage :: Fractional t => Int -> [t] -> [t]
    movingAverage n list = map (/ (fromIntegral n)) (slidingSums n list)
    
    paddedMovingAverage :: Fractional t => Int -> [t] -> [t]
    paddedMovingAverage n list = replicate (n - 1) 0 ++ movingAverage n list
    

    Scala translation:

    def slidingSums1(list: List[Double], rest: List[Double], n: Int, sumLastNm1: Double): List[Double] = rest match {
        case Nil => Nil
        case hr :: tr => {
            val sumLastN = sumLastNm1 + hr
            sumLastN :: slidingSums1(list.tail, tr, n, sumLastN - list.head)
        }
    }
    
    def slidingSums(list: List[Double], n: Int): List[Double] = list.splitAt(n - 1) match {
        case (_, Nil) => Nil
        case (firstNm1, rest) => slidingSums1(list, rest, n, firstNm1.reduceLeft(_ + _))
    }
    
    def movingAverage(list: List[Double], n: Int): List[Double] = slidingSums(list, n).map(_ / n)
    
    def paddedMovingAverage(list: List[Double], n: Int): List[Double] = List.make(n - 1, 0.0) ++ movingAverage(list, n)
    

提交回复
热议问题