3

我想使用单个循环遍历 one 的所有元素Set,然后遍历 another 的所有元素。Set(我不关心重复,因为我碰巧知道这两个Sets 是不相交的。)

我想在一个循环中执行它的原因是因为我有一些额外的代码来衡量进度,这要求它在一个循环中。

这通常不起作用,因为它可能会Set任意混合两者:

for(x <- firstSet ++ secondSet) {
   ...
}

这可行,但在内存中构建了 3 个中间Seqs,因此在时间和空间使用方面都太低效了:

for(x <- firstSet.toSeq ++ secondSet.toSeq) {
   ...
}
4

2 回答 2

11
for(x <- firstSet.toIterator ++ secondSet.toIterator) {
   ...
}

这不会构建任何中间数据结构,所以我认为这是最有效的方式。

于 2013-06-29T08:41:56.433 回答
5

如果您只想要遍历,并且想要最大性能,那么这是最好的方法,即使它很丑:

val s1 = Set(1,2,3)
val s2 = Set(4,5,6)
val block : Int => Unit = x => { println(x) }
s1.foreach(block)
s2.foreach(block)

由于这很丑陋,您可以为它定义一个类:

def traverse[T](a:Traversable[T], b:Traversable[T]) : Traversable[T] = 
  new Traversable[T] { 
    def foreach[U](f:T=>U) { a.foreach(f); b.foreach(f) } 
  }

然后像这样使用它:

for(x<-traverse(s1, s2)) println(x)

但是,除非这对性能非常关键,否则 Robin Green 发布的解决方案会更好。开销是创建两个迭代器并将它们连接起来。如果你有更深的嵌套数据结构,连接迭代器可能会非常昂贵。例如,通过连接子树的迭代器定义的树迭代器将非常缓慢,而您只需在每个子树上调用 foreach 的可遍历树将接近最优。

于 2013-06-29T09:07:13.827 回答