问题
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