Промежуточные значения при складывании? - PullRequest
1 голос
/ 08 мая 2020

У меня есть набор объектов

case class Record(value: Whatever)
val list: List[Record]

и я хочу выбрать лучший по рейтингу

list.foldLeft(list.head) { (best, current) =>
    if (rank(current.value) > rank(best.value)) {
        current
    } else {
        best
    }
}

Предположим, что rank дорого стоит и лучше не вызывать дважды на тот же объект. Какие у меня варианты?

Я могу свернуть до кортежа (rank, record), но это, вероятно, означает создание вспомогательных объектов во время итерации. Стоит ли беспокоиться о накладных расходах? Или, скорее,

  1. Как это может быть эффективно реализовано в Scala?

  2. Каков правильный «функциональный» взгляд на проблему?

Ответы [ 2 ]

4 голосов
/ 08 мая 2020

Если вы находитесь в ситуации, когда повторение дорогостоящих вычислений для одних и тех же объектов кажется неизбежным, вы можете попробовать мемоизацию.

// memoize this function (arity 1)
def memo[A,R](f :A => R): A => R =
  new collection.mutable.WeakHashMap[A,R] {
    override def apply(a: A) = getOrElseUpdate(a,f(a))
  }

// rankM is a memoized Record => Rank function
val rankM = memo{ r:Record => rank(r.value) }

A WeakHashMap используется иногда, когда вы хотите, чтобы Map «забыть» редко используемые ключи в среде с ограниченными возможностями памяти.

2 голосов
/ 08 мая 2020

Начальное значение в foldLeft может быть другого типа, чем коллекция, поэтому вы можете инициализировать его кортежем, который будет содержать текущий элемент и вычисленное значение:

val (result, _) = list.foldLeft((list.head, rank(list.head))) { case ((best, bestRank), current) =>
    val currentRank = rank(current.value)
    if (rank(current.value) > bestRank) {
      (current, currentRank)
    } else {
      (best, bestRank)
    }
}

Но, как упоминалось в комментариях, возможно в вашем случае было бы лучше просто использовать: list.maxBy(r => rank(r.value))?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...