不知道这是否可行,但我有一些这样的代码:
val list = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)
val evens = list.filter { e => e % 2 == 0 }
if(someCondition) {
val result = evens.filter { e => e % 3 == 0 }
} else {
val result = evens.filter { e => e % 5 == 0 }
}
Run Code Online (Sandbox Code Playgroud)
但是我不想迭代所有元素两次,所以有没有办法让我可以在这个集合上创建"泛型选择全部数字"并应用其他一些函数,这样它只会迭代一次?
dhg*_*dhg 26
如果你list变成一个惰性集合,比如a Iterator,那么你可以map在一遍中应用所有过滤操作(或其他类似的东西):
val list = (1 to 12).toList
val doubleFiltered: List[Int] =
list.iterator
.filter(_ % 2 == 0)
.filter(_ % 3 == 0)
.toList
println(doubleFiltered)
Run Code Online (Sandbox Code Playgroud)
当您将集合转换为Iterator时.iterator,Scala将跟踪要执行的操作(此处为两个filter),但是将等待执行它们直到实际访问结果(此处,通过调用.toList).
所以我可能会像这样重写你的代码:
val list = (1 to 12).toList
val evens = list.iterator.filter(_ % 2 == 0)
val result =
if(someCondition)
evens.filter(_ % 3 == 0)
else
evens.filter(_ % 5 == 0)
result foreach println
Run Code Online (Sandbox Code Playgroud)
根据您想要做什么,您可能需要a Iterator,a Stream或a View.它们都是懒惰计算的(因此一次通过方面将适用),但它们的不同之处在于它们是否可以多次迭代(Stream和View),或者它们是否保留计算值以供以后访问(Stream).
要真正看到这些不同的懒惰行为,尝试运行这段代码,并设置<OPERATION>要么toList,iterator,view,或toStream:
val result =
(1 to 12).<OPERATION>
.filter { e => println("filter 1: " + e); e % 2 == 0 }
.filter { e => println("filter 2: " + e); e % 3 == 0 }
result foreach println
result foreach println
Run Code Online (Sandbox Code Playgroud)
以下是您将看到的行为:
List(或任何其他非惰性集合):每个集合都filter需要单独迭代.生成的过滤集合存储在内存中,以便每个集合都foreach可以显示它.Iterator:filters和第一个foreach都是在一次迭代中完成的.第二个foreach因为Iterator消耗已经没有做任何事情.结果不存储在内存中.View:两个foreach调用都会导致它们在集合上进行单次迭代以执行filters.结果不存储在内存中.Stream:filters和第一个foreach都是在一次迭代中完成的.生成的过滤集合存储在内存中,以便每个集合都foreach可以显示它.你可以使用功能组合.someCondition在决定使用哪个函数时,这里只调用一次:
def modN(n: Int)(xs: List[Int]) = xs filter (_ % n == 0)
val f = modN(2) _ andThen (if (someCondition) modN(3) else modN(5))
val result = f(list)
Run Code Online (Sandbox Code Playgroud)
(这不是你想要的 - 它仍然遍历列表两次)
这样做:
val f: Int => Boolean = if (someCondition) { _ % 3 == 0 } else { _ % 5 == 0 }
val result = list filter (x => x % 2 == 0 && f(x))
Run Code Online (Sandbox Code Playgroud)
或者更好:
val n = if (someCondition) 3 else 5
val result = list filter (x => x % 2 == 0 && x % n == 0)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
16676 次 |
| 最近记录: |