2013-05-03 178 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