Не уверен, как реализовать стандартное отклонение через рекурсию - PullRequest
0 голосов
/ 13 марта 2020

Итак, у меня есть настроенный метод generi c, состоящий из:

  • Параметр типа T
  • Список T (который будет набором данных, который я будет смотреть)
  • Функция от T до удвоения (Эта функция будет использоваться для получения свойства от каждого элемента данных. Поэтому в основном это свойство используется для вычисления и возврата стандартного отклонения.) Например, List (7.63, 3.87, 1.59, 8.26, 5.11, 0.65, 7.88) должен вернуть 3.100496888

Эта последняя пуля сбивает меня с толку, и я не уверен, как выразить ее в форме рекурсии.

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

  }
```

Извините за отсутствие опыта. Функциональное программирование - это не моя сильная сторона.

Ответы [ 2 ]

3 голосов
/ 13 марта 2020

Вам не нужна рекурсия. Это может быть вычислено с использованием foldLeft:

elements.foldLeft(0) {
   case (accumulator, item) => ...//calculate here next value from previously calculated 
                                  //value (accumulator) and current item
}
2 голосов
/ 13 марта 2020

Если вы не хотите изменять сигнатуру, вам придется использовать локальную функцию и сделать эту функцию хвостовой рекурсивной

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

Когда вы выполняете хвостовую рекурсивную обработку, вы должны каким-то образом передавать результаты: до сих пор, так что если вы не можете представить промежуточные результаты в API, это единственный способ.

Однако вам не нужно реализовывать это с помощью tail re c, а вместо этого использовать некоторый функциональный подход вместо:

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))
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...