Not sure how to implement the standard deviation through recursion

后端 未结 2 1581
说谎
说谎 2021-01-26 04:47

So I have the generic method set up consisting of:

  • A parameter of type T
  • A List of T\'s (which will be the data set that I will be looking at)
  • A
相关标签:
2条回答
  • 2021-01-26 05:44

    You don't need recursion. This could be computed using foldLeft:

    elements.foldLeft(0) {
       case (accumulator, item) => ...//calculate here next value from previously calculated 
                                      //value (accumulator) and current item
    }
    
    0 讨论(0)
  • 2021-01-26 05:45

    If you don't want to change the signature you would have to use local function and make that function tail-recursive

    def standardDeviation[T](elements: List[T], property: T => Double): Double = {
      val values = elements.map(property)
      val size = elements.size.toDouble
      // this could acually be replaced by values.sum
      @scala.annotation.tailrec
      def calculateSum(remaining: List[Double], acc: Double): Double = remaining match {
        case head :: tail => calculateSum(tail, acc + head)
        case Nil          => acc
      }
      val mean = calculateSum(values, 0.0) / size
      @scala.annotation.tailrec
      def calculateSumOfDiffs(remaining: List[Double], acc: Double): Double = remaining match {
        case head :: tail => calculateSumOfDiffs(tail, acc + Math.pow(head - mean, 2.0))
        case Nil          => acc
      }
      Math.sqrt(calculateSumOfDiffs(values, 0.0) / (size - 1))
    }
    
    

    When you are doing tail recursive computation you have to somehow pass results-so-far, so if you cannot expose the intermediate results in API, this is the only way.

    However, you don't have to implement this using tail rec, but instead use some functional approach instead:

    def standardDeviation[T](elements: List[T], property: T => Double): Double = {
      val values = elements.map(property)
      val size = values.size.toDouble
      val mean = values.sum / size
      Math.sqrt(values.map(x => Math.pow(x - mean, 2.0)).sum / (size - 1))
    }
    
    0 讨论(0)
提交回复
热议问题