Scala 合并集合操作

Scala 合并集合操作,scala,collections,functional-programming,scala-collections,Scala,Collections,Functional Programming,Scala Collections,请看下面的代码: val a = List(1,2,3,4,5) a.filter(_ >= 3).map(_ * 9).drop(1).take(2) 我的理解是,对于每个操作,它会在列表中迭代一次,生成类似以下内容的代码: for(i <- a) { // filter } for (i <- afiltered) { // map } for (i <- afilteredandmapped) { // drop } ..etc for(iS

请看下面的代码:

val a = List(1,2,3,4,5)
a.filter(_ >= 3).map(_ * 9).drop(1).take(2)
我的理解是,对于每个操作,它会在列表中迭代一次,生成类似以下内容的代码:

for(i <- a) {
    // filter
}
for (i <- afiltered) {
   // map
}
for (i <- afilteredandmapped) {
   // drop
}
..etc

for(iScala 2.8集合引入了a的概念,它是严格集合的惰性对应物。它允许您在对集合应用多个转换时避免集合的中间分配

您可以通过调用集合上的
.view
来使用它们,当您想要具体化它们时,您可以通过
.force
toList
/
.toSeq
:

val result = a
              .view
              .filter(_ >= 3)
              .map(_ * 9)
              .drop(1)
              .take(2)
              .force

Scala集合得到了热切的评估。防止创建中间集合的最简单、最可靠的方法是将转换应用于迭代器,而不是集合本身:

val a = List(1,2,3,4,5)
a.filter(_ >= 3).map(_ * 9).drop(1).take(2)
除了结果之外,还创建3个中间列表

val a = List(1,2,3,4,5)
a.iterator.filter(_ >= 3).map(_ * 9).drop(1).take(2).toList
仅创建结果列表


这与Yuval Itzachow的解决方案非常相似。但是视图要复杂一些,因为它们试图保留集合的类型(每个集合都有一个对应的视图),因此,如果您不介意说明您希望结果是什么,那么迭代器方法更可取
toList
force

,您可以在
collect
中组合
过滤器
映射

val a = List(1,2,3,4,5)
a.collect {case x if x >= 3 => x * 9}.drop(1).take(2)
如果你想让drop和take变得懒惰,你需要视图、迭代器或流

val xs = a.toStream
xs.filter{x=>println("filtering " + x); x >= 3}
  .map{x=>println("mapping " + x); x * 9}
  .drop(1)
  .take(2)
  .toList
//> filtering 1
//| filtering 2
//| filtering 3
//| mapping 3
//| filtering 4
//| mapping 4
//| filtering 5
//| mapping5
//| res1: List[Int] = List(36, 45)

为了理解这些情况,我们将代表您组合这些操作,并为您生成有效的代码

(for (x <- a if x >= 3 ) yield (x * 9)).drop(1).take(2)
(对于(x=3)收益率(x*9))。下降(1)。下降(2)
事实上,对于理解,它被转化为withFilter和map/flatmap的组合


withFilter是在使用方法链时专门设计的,用于启用惰性评估。过滤器会获取一个集合并当场生成一个新集合。但是withFilter不做任何操作,而是将未过滤的数据传递给下一个操作。因此,如果下一个操作是一个映射,则会实现结果并生成整个filter+map组合是一起评估的。

使用
Stream
而不是
List
。这就是
view
应该做的,但它还有一些其他微妙的效果:
a.view.filter(>=3).map(*9).drop(1).take(2).toList
(for (x <- a if x >= 3 ) yield (x * 9)).drop(1).take(2)