簡體   English   中英

Scala,foldLeft和地圖之間的交叉,支持惰性評估

[英]Scala, a cross between a foldLeft and a map supporting lazy evaluation

我有一個要映射到新集合的集合,但是每個結果值都以某種方式取決於它之前的值。我可以用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)]

您可能可以使用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)

我真的不理解您的示例,因為您的包含檢查將始終為false

foldLeft是不同的。 通過匯總列表的所有元素,將得到一個單一值。 您顯然需要mapList => List )。

無論如何,回答關於懶惰的問題:您應該使用Stream而不是List Stream在實際調用它之前不會評估它的尾巴。

流API

看起來您需要SeqView 使用viewview(from: Int, until: Int)方法創建列表的非嚴格視圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM