1

我有一个集合,我想映射到一个新集合,但是每个结果值都以某种方式依赖于它之前的值。我可以用 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)]
4

3 回答 3

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)
于 2013-11-07T22:18:12.170 回答
0

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

于 2013-11-07T16:58:00.030 回答
0

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

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

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

流 API

于 2013-11-07T16:49:38.033 回答