【问题标题】:Is there a combination of foldLeft and for-yield?是否有 foldLeft 和 for-yield 的组合?
【发布时间】:2011-11-22 17:33:18
【问题描述】:

我必须处理订单序列(这里是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(var 和 yield builder):

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 中保存显式构建器或在版本 2 中保存可变 var

这可能吗?也许是foldLeftfor-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],所以VectorList 没有区别。

【问题讨论】:

    标签: scala collections yield fold


    【解决方案1】:
    orders.tail.scanLeft(handleOrders(prev, orders)) { (p, o) => handleOrder(p, o) }
    

    scanLeftfoldLeft 的作用相同,但保留所有中间结果。您可以通过排除集合的head 来摆脱这种特殊情况,您可以使用orders.tail 来执行此操作。

    【讨论】:

    • 谢谢,我喜欢! case 关键字是否有特殊含义,还是只是口味问题?因为orders.tail.scanLeft(handleOrders(prev, orders)) { (p, o) =&gt; handleOrder(p, o) } 甚至orders.tail.scanLeft(handleOrders(prev, orders)) { handleOrder(_, _) } 也能胜任。
    • 你是对的。不必使用case。我想我是出于习惯而写的(在更复杂的比赛中需要它)。 (case 甚至可能会慢一点。)
    • 我使用(p, o) =&gt; 版本,以便更清楚地知道哪个是哪个。最后,这确实是一个品味问题。
    猜你喜欢
    • 2017-06-12
    • 1970-01-01
    • 2013-05-15
    • 1970-01-01
    • 2012-04-26
    • 2016-01-02
    • 1970-01-01
    • 1970-01-01
    • 2018-09-25
    相关资源
    最近更新 更多