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)