加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

Scala List.filter有两个条件,只应用一次

发布时间:2020-12-16 19:00:57 所属栏目:安全 来源:网络整理
导读:不知道这是否可行,但我有一些这样的代码: 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 ==
不知道这是否可行,但我有一些这样的代码:

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可以显示它.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读