2013-05-03 98 views
2

我是新来Scala和我有一个函数如下怪异的行为:斯卡拉 - 与Iterator.toList

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

这是从一个缓冲的迭代器只选择相匹配的头elems的。我随后使用此代码:

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),但后来我只得到列表(2),就像如果我失去了一个元素向下行...可能我正在用迭代器/列表做错,但我在这里有点失落。

+0

对不起,我的意思List.iterator.buffered。道歉 – user221218 2013-05-03 14:54:14

回答

5

Iterator Scaladoc说,大约takeWhile

重用:调用此方法后,应该丢弃 拜访了迭代器,并只使用返回迭代器。使用 旧迭代器未定义,可能会更改,也可能导致 更改为新迭代器。

所以这就是为什么。这基本上意味着你不能直接做你想用IteratorstakeWhile。恕我直言,最简单的办法就是快速编写自己的递归函数来做到这一点。

如果您想坚持使用Iterators,您可以使用Iterator上的sameElements方法生成重复的地方,您可以拨打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 
} 
+0

+1:为了测试它是否仍然等于'1',必须消耗第一个'2'元素。所以,正如文档所警告的那样,迭代器的状态并不像预期的那样。 – 2013-05-03 14:54:50

+0

非常感谢这个答案。任何想法都可以实现相同的功能,即以功能的方式从迭代器中选择前N个相同的对象? – user221218 2013-05-03 14:55:27

+0

@ user221218查看编辑答案 – gzm0 2013-05-03 15:02:06