Есть ли комбинация foldLeft и for-yield? - PullRequest
1 голос
/ 22 ноября 2011

Я должен обработать с последовательностями заказов (здесь Int для упрощения):

// the handleOrder methods are in fact much more complicated:
def handleOrders(prev: Double, orders: Seq[Int]): Double = prev + orders.sum
def handleOrder(prev: Double, order: Int): Double = prev / order

В результате так называемого

def nextGroup(prev: Double, orders: Seq[Int]): Seq[Double]

функция Я получаю последовательность другого класса (здесь Double для упрощения).

Исходя из этого, я реализовал две версии.

Версия 1 (foldLeft и явный построитель):

def nextGroup1(prev: Double, orders: Seq[Int]): Seq[Double] = {
  import collection.mutable.Builder
  import collection.immutable.VectorBuilder
  val bld: Builder[Double, Seq[Double]] = new VectorBuilder[Double]
  var first = true
  orders.foldLeft(prev) { (prev, order) =>
    val step = if (first) handleOrders(prev, orders) else prev
    val next = handleOrder(step, order)
    first = false
    bld += next
    next
  }
  bld.result
}

Версия 2 (вар и для построителя урожая):

def nextGroup2(prev: Double, orders: Seq[Int]): Seq[Double] = {
  var first = true
  var präv = prev
  for (order <- orders) yield {
    if (first) präv = handleOrders(präv, orders)
    präv = handleOrder(präv, order)
    first = false
    präv
  }
}

Я бы хотел сохранить явный построитель в версии 1 или изменяемый var в версии 2.

Возможно ли это? Возможно, с комбинацией foldLeft и for - yield?

И еще что-то пример данных:

val orders = Seq(1, 2, 3)
nextGroup1(1d, orders) // => Vector(7.0, 3.5, 1.1666666666666667)
nextGroup2(1d, orders) // => List(7.0, 3.5, 1.1666666666666667)
nextGroup1(2d, orders) // => Vector(8.0, 4.0, 1.3333333333333333)
nextGroup2(2d, orders) // => List(8.0, 4.0, 1.3333333333333333)

Результаты nextGroup обрабатываются как Seq[Double], поэтому Vector или List не имеют значения.

1 Ответ

6 голосов
/ 22 ноября 2011
orders.tail.scanLeft(handleOrders(prev, orders)) { (p, o) => handleOrder(p, o) }

scanLeft делает то же самое, что и foldLeft, но сохраняет все промежуточные результаты. Вы можете избавиться от особого случая, исключив head из коллекции, которую вы можете сделать, используя orders.tail.

...