Итератор Scala с картой и для

Данный:

val list = List("one","two","three")     
val it = list.toIterator

Я могу бегать:

list map ("_" +) -> List(_one, _two, _three)
for (i <- list) yield("_" + i) -> List(_one, _two, _three)

Если я запускаю то же самое на итераторе, я получаю:

it map ("_" + ) -> Iterator[java.lang.String] = empty iterator
for (i <- it) yield("_" + i) -> Iterator[java.lang.String] = empty iterator

Разве я не должен вернуть другой (не пустой) итератор [String] после того, как я запустил на нем map/for?


person ssanj    schedule 03.02.2011    source источник


Ответы (2)


scala> def ints(n: Int): Stream[Int] = n #:: ints(n + 1)
ints: (n: Int)Stream[Int]

scala> val list = List("one","two","three")
list: List[java.lang.String] = List(one, two, three)

scala> val it = list.toIterator
it: Iterator[java.lang.String] = non-empty iterator

scala> it map ("_" + )
res24: Iterator[java.lang.String] = non-empty iterator

scala> it map ("_" + )
res25: Iterator[java.lang.String] = non-empty iterator

scala> for (i <- it) yield("_" + i)
res26: Iterator[java.lang.String] = non-empty iterator

Может быть, вы использовали свой итератор?

scala> res26.foreach{println}
_one
_two
_three

scala> res26
res28: Iterator[java.lang.String] = empty iterator

Поскольку итераторы сохраняют состояние и не могут быть сброшены, после того, как вы их использовали, они пусты и не могут быть использованы снова.

Вместо этого вы можете использовать представления:

scala> val v = list.view
v: java.lang.Object with scala.collection.SeqView[java.lang.String,List[java.lang.String]] = SeqView(one, two, three)

scala> v map ("_" + )
res29: scala.collection.SeqView[java.lang.String,Seq[_]] = SeqViewM(...)

scala> for (i <- v) yield("_" + i)
res30: scala.collection.SeqView[java.lang.String,Seq[_]] = SeqViewM(...)

scala> res29.foreach{println}
_one
_two
_three

scala> res29
res32: scala.collection.SeqView[java.lang.String,Seq[_]] = SeqViewM(...)

scala> res29.foreach{println}
_one
_two
_three
person IttayD    schedule 03.02.2011
comment
Ты прав! Должно быть, я использовал итератор до того, как наткнулся на примеры. Спасибо! :) - person ssanj; 03.02.2011

См. раздел Итераторы.

Существует важное различие между методом foreach для итераторов и тем же методом для проходимых коллекций: при вызове итератора foreach оставит итератор в конце, когда это будет сделано. Таким образом, повторный вызов next на том же итераторе завершится ошибкой с NoSuchElementException. Напротив, при вызове для коллекции foreach оставляет количество элементов в коллекции неизменным (если только переданная функция не добавляет элементы, а удаляет их, но это не рекомендуется, поскольку может привести к неожиданным результатам).

...

Как видите, после вызова it.map итератор it дошел до конца.

person Eugene Yokota    schedule 03.02.2011