Not sure how to implement the standard deviation through recursion

自作多情 提交于 2020-06-09 05:46:05

问题


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 function from T to double (This function will be used to take a property from each data element. So basically the property is used to compute the and return standard deviation.) For example the List(7.63, 3.87, 1.59, 8.26, 5.11, 0.65, 7.88) should return 3.100496888

That last bullet is confusing me and I'm not sure how to put it in the form of recursion.

```
  def standardDeviation[T](elements: List[T], property: T => Double): Double = {

  }
```

Sorry for my lack of experience. Functional programming is just not my strong spot.


回答1:


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



回答2:


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
}


来源:https://stackoverflow.com/questions/60672327/not-sure-how-to-implement-the-standard-deviation-through-recursion

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!