Scala - Iterator.toList的奇怪行为

时间:2013-05-03 14:44:16

标签: scala iterator

我是Scala的新手,我的功能如下:

def selectSame(messages: BufferedIterator[Int]) = {
  val head = messages.head
  messages.takeWhile(_ == head)
}

从缓冲的迭代器中选择只匹配头部的元素。我随后使用此代码:

val messageStream = List(1,1,1,2,2,3,3)
if (!messageStream.isEmpty) {
  var lastTimeStamp = messageStream.head.timestamp
  while (!messageStream.isEmpty) {
    val messages = selectSame(messageStream).toList
    println(messages)
}

第一次执行时,我按预期获得(1,1,1),但后来我只获得了List(2),就好像我丢失了一个元素......可能我做错了迭代器/列表,但我在这里有点迷失。

1 个答案:

答案 0 :(得分:5)

Iterator的Scaladoc说takeWhile

  

重用:调用此方法后,应该丢弃迭代器   被调用,并只使用返回的迭代器。使用   旧迭代器未定义,可能会发生变化,并可能导致   也改变了新的迭代器。

所以这就是原因。这基本上意味着您无法使用IteratorstakeWhile直接执行所需操作。恕我直言,最简单的是快速编写自己的递归函数来做到这一点。

如果您想坚持使用Iterators,可以使用sameElements上的Iterator方法生成重复的地方dropWhile

更好:重复使用span

def selectSame(messages: BufferedIterator[Int]) = {
  val head = messages.head
  messages.span(_ == head)
}

def iter(msgStream: BufferedIterator[Int]): Unit = if (!msgStream.isEmpty) {
  val (msgs, rest) = selectSame(msgStream)
  println(msgs.toList)
  iter(rest)
}

val messageStream = List(1,1,1,2,2,3,3)
if (!messageStream.isEmpty) {
  var lastTimeStamp = messageStream.head.timestamp
  iter(messageStream0
}