2013-05-03 5 views
2

Я новичок в Scala и у меня есть функция следующим образом: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

ответ

5

Scaladoc из Iterator говорит о takeWhile:

Повторное использование: После вызова этого метода следует отказаться от итератора он был вызван на, и использовать только итератор, который был возвращен. Использование старого итератора не определено, может быть изменено и может привести к изменениям в новом итераторе .

Так вот почему. Это в основном означает, что вы не можете напрямую делать то, что хотите, с Iterators и takeWhile. ИМХО, проще всего было бы быстро написать свою собственную рекурсивную функцию для этого.

Если вы хотите придерживаться 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 
} 
+0

+1: Первый элемент '2' должен быть использован, чтобы проверить, все ли он равен' 1'. Таким образом, как предупреждает docs, состояние итератора не так, как ожидалось. –

+0

Большое спасибо за этот ответ. Любая идея для достижения той же функциональности, то есть выбор первого N тех же объектов из итератора функциональным способом? – user221218

+0

@ user221218 См. Отредактированный ответ – gzm0

Смежные вопросы