【问题标题】:Scala, a cross between a foldLeft and a map supporting lazy evaluationScala,foldLeft 和支持惰性求值的映射之间的交叉
【发布时间】:2013-11-07 16:33:30
【问题描述】:

我有一个集合,我想将它映射到一个新集合,但是每个结果值都以某种方式依赖于它之前的值。我可以用 leftFold 解决这个问题

val result:List[B] = (myList:List[A]).foldLeft(C -> List.empty[B]){ 
  case ((c, list), a) =>
    ..some function returning something like..
    C -> (B :: list)
} 

这里的问题是我需要遍历整个列表来检索结果列表。假设我想要一个将 TraversableOnce[A] 映射到 TraversableOnce[B] 并且只评估我调用的成员的函数? 在我看来,这似乎是一个相当传统的问题,所以我想知道是否有一种通用的方法来解决这个问题。我目前拥有的是:

implicit class TraversableOnceEx[T](val self : TraversableOnce[T]) extends AnyVal {

   def foldyMappyFunction[A, U](a:A)(func:(A,T) => (A,U)):TraversableOnce[U] = {
     var currentA = a
     self.map { t =>
        val result = func(currentA, t)
        currentA = result._1
        result._2
     }
   } 
}

就功能纯度而言,您无法并行运行它,但除此之外它看起来还不错。

一个例子是; 将每个元素返回给我,如果它是该元素之前第一次出现。

val elements:TraversableOnce[E]
val result = elements.mappyFoldyFunction(Set.empty[E]) {
 (s, e) => (s + e) -> (e -> s.contains(e))
}
result:TraversableOnce[(E,Boolean)]

【问题讨论】:

  • 你能添加一个调用你的foldyMappingFunction的例子吗?
  • 我已经更新了示例

标签: scala map lazy-evaluation fold


【解决方案1】:

您也许可以使用 State Monad。这是您使用 scalaz 重写的示例:

import scalaz._, Scalaz._

def foldyMappy(i: Int) = State[Set[Int], (Int, Boolean)](s => (s + i, (i, s contains(i))))

val r = List(1, 2, 3, 3, 6).traverseS(foldyMappy)(Set.empty[Int])._2

//List((1,false), (2,false), (3,false), (3,true), (6,false))
println(r)

【讨论】:

    【解决方案2】:

    看起来你需要SeqView。使用viewview(from: Int, until: Int) 方法创建非严格的列表视图。

    【讨论】:

      【解决方案3】:

      我真的不明白你的例子,因为你的包含检查总是会导致false

      foldLeft 不同。它将通过聚合列表的所有元素产生单个值。 你显然需要map (List => List)。

      无论如何,回答你关于懒惰的问题: 你应该使用Stream 而不是ListStream 在实际调用它之前不会评估尾部。

      Stream API

      【讨论】:

      • 或者它的类似物在被使用后试图不将自己保存在内存中:迭代器
      猜你喜欢
      • 1970-01-01
      • 2011-12-07
      • 2011-01-15
      • 1970-01-01
      • 1970-01-01
      • 2016-03-23
      • 2020-06-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多