2011-02-03 4 views
10

Dato:Scala Iterator con Mappa e Per

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

posso correre:

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

Se corro lo stesso sul iteratore ottengo:

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

Non dovrebbe Ricevo un altro (non vuoto) Iterator [String] dopo che eseguo map/for su di esso?

risposta

15
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 

Forse hai usato il tuo iteratore?

scala> res26.foreach{println} 
_one 
_two 
_three 

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

Dal iteratori sono stateful e non azzerabile, una volta che è stato utilizzato, esso è vuoto e non può essere riutilizzato.

Invece, è possibile utilizzare le visualizzazioni:

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 
+1

Hai ragione! Devo aver usato l'Iterator prima di eseguire gli esempi. Grazie! :) – ssanj

3

Vedi Iterators.

C'è una differenza importante tra il metodo foreach sul iteratori e lo stesso metodo su collezioni attraversabili: Quando è chiamato ad un iteratore, foreach lascerà l'iteratore alla sua estremità quando è fatto. Quindi chiamare lo next di nuovo sullo stesso iteratore fallirà con un NoSuchElementException. Al contrario, quando viene richiamato su una raccolta, foreach lascia il numero di elementi nella raccolta invariato (a meno che la funzione passata non aggiunga elementi rimossi, ma ciò è scoraggiato, perché può portare a risultati sorprendenti).

...

Come si può vedere, dopo la chiamata a it.map, il it iteratore ha avanzato alla sua fine.