Scala List.filter有两个条件,只应用一次
不知道这是否可行,但我有一些这样的代码:
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 } } 但是我不想迭代所有元素两次,所以有一种方法可以在这个集合上创建一个“通用的pick-all-the-evens数字”,并应用一些其他的函数,这样它只会迭代一次? 解决方法
如果您将列表转换成一个惰性的集合,例如迭代器,那么您可以在一次通过中应用所有的过滤器操作(或地图等):
val list = (1 to 12).toList val doubleFiltered: List[Int] = list.iterator .filter(_ % 2 == 0) .filter(_ % 3 == 0) .toList println(doubleFiltered) 当您将集合转换为带有.iterator的迭代器时,Scala将跟踪要执行的操作(这里是两个过滤器),但将等待执行,直到实际访问结果(此处通过调用.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 根据您想要做什么,您可能需要一个迭代器,一个流或视图.它们都是懒惰的计算(所以一次通过的方面将会适用),但是它们的区别在于它们是否可以被多次迭代(Stream和View),或者它们是否保留计算值以供稍后访问(Stream). 要真正看到这些不同的懒惰行为,请尝试运行该位代码并设置< OPERATION> to 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 以下是您将看到的行为: >列表(或任何其他非懒惰集合):每个过滤器都需要通过集合进行单独的迭代.所得到的过滤集合存储在内存中,以便每个foreach可以显示它.>迭代器:两个过滤器和第一个foreach都是在单次迭代中完成的.自从迭代器被消耗以来,第二个foreach什么都不做.结果不存储在内存中.>查看:两个foreach调用都会在集合中产生自己的单遍迭代来执行过滤器.结果不存储在内存中.流:两个过滤器和第一个foreach都是在单次迭代中完成的.所得到的过滤集合存储在内存中,以便每个foreach可以显示它. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |