Scala-合并多个迭代器

Scala-合并多个迭代器,scala,iterator,Scala,Iterator,我有多个迭代器,它们根据某种排序标准以排序方式返回项。现在,我想把迭代器合并成一个组合迭代器。我知道如何使用Java风格,例如树形图,但我想知道是否有更实用的方法?我希望尽可能保持迭代器的惰性。您可以执行以下操作: val it = iter1 ++ iter2 它创建另一个迭代器,不计算元素,而是包装两个现有迭代器。 它是完全懒惰的,因此一旦您这样做,就不应该使用iter1或iter2 通常,如果要合并更多迭代器,可以使用折叠: val iterators: Seq[Iterator[T]]

我有多个迭代器,它们根据某种排序标准以排序方式返回项。现在,我想把迭代器合并成一个组合迭代器。我知道如何使用Java风格,例如树形图,但我想知道是否有更实用的方法?我希望尽可能保持迭代器的惰性。

您可以执行以下操作:

val it = iter1 ++ iter2
它创建另一个迭代器,不计算元素,而是包装两个现有迭代器。 它是完全懒惰的,因此一旦您这样做,就不应该使用
iter1
iter2

通常,如果要合并更多迭代器,可以使用折叠:

val iterators: Seq[Iterator[T]] = ???
val it = iterators.foldLeft(Iterator[T]())(_ ++ _)
如果您希望在生成的迭代器中维护元素的某些顺序,但您需要懒散,则可以将它们转换为流:

def merge[T: Ordering](iter1: Iterator[T], iter2: Iterator[T]): Iterator[T] = {
  val s1 = iter1.toStream
  val s2 = iter2.toStream

  def mergeStreams(s1: Stream[T], s2: Stream[T]): Stream[T] = {
    if (s1.isEmpty) s2
    else if (s2.isEmpty) s1
    else if (s1.head < s2.head) s1.head #:: mergeStreams(s1.tail, s2)
    else s2.head #:: mergeStreams(s1, s2.tail)
  }

  mergeStreams(s1, s2).iterator
}
def merge[T:Ordering](iter1:Iterator[T],iter2:Iterator[T]):Iterator[T]={
val s1=iter1.toStream
val s2=iter2.toStream
def合并流(s1:流[T],s2:流[T]):流[T]={
如果(s1.isEmpty)s2
如果(s2.isEmpty)s1
如果(s1.head
但不一定要快,你应该把它标上

一种可能的替代方法是使用以达到相同的效果。

您可以尝试:

(iterA ++ iterB).toStream.sorted.toIterator
例如:

val i1 = (1 to 100 by 3).toIterator val i2 = (2 to 100 by 3).toIterator val i3 = (3 to 100 by 3).toIterator val merged = (i1 ++ i2 ++ i3).toStream.sorted.toIterator merged.next // results in: 1 merged.next // results in: 2 merged.next // results in: 3 val i1=(1到100乘以3).t计数器 val i2=(2到100乘以3).t计数器 val i3=(3到100乘以3).t计数器 val merged=(i1++i2++i3).toStream.sorted.toInterator merged.next//结果为:1 merged.next//结果为:2 merged.next//结果为:3
就像前面提到的@axel22一样,您可以使用buffereditor来实现这一点。这里有一个无流解决方案:

def combine[T](rawIterators: List[Iterator[T]])(implicit cmp: Ordering[T]): Iterator[T] = {
  new Iterator[T] {
    private val iterators: List[BufferedIterator[T]] = rawIterators.map(_.buffered)

    def hasNext: Boolean = iterators.exists(_.hasNext)

    def next(): T = if (hasNext) {
      iterators.filter(_.hasNext).map(x => (x.head, x)).minBy(_._1)(cmp)._2.next()
    } else {
      throw new UnsupportedOperationException("Cannot call next on an exhausted iterator!")
    }
}

好的,我如何确保根据相同的排序标准保持相对排序?假设我有一个对象,其时间戳的形式为
DateTime
。我希望这两个迭代器根据时间戳合并,而不是一个接一个地合并(在Java中,我会使用comparator),谢谢,但我确实不想使用流,因为它们缓存元素。此外,我是否可以提供实际元素的排序,例如Java Comparator中的排序,您可以将其作为参数传递给集合?在示例中,这是通过使用
T
上的
排序
上下文绑定来完成的。
内存占用复杂度和渐进运行时复杂度在流中保持不变-只有绝对性能可能更差。“内存占用复杂度和渐进运行时复杂度在流中保持不变”-这要求在内存复杂度方面有所不同OOPS,我的坏消息。我知道您不想使用Streams。的可能重复