Ho bisogno di un metodo che può dividere Iterator[Char]
in linee (separati da \n
e \r
)dividere un iteratore da un predicato
Per questo, ho scritto un metodo generale che ottiene un iteratore e un predicato e dividerà l'iteratore ogni volta che il predicato è vero. Questo è simile a span
, ma sarà diviso ogni volta che il predicato è vero, non solo la prima volta
questa è la mia realizzazione:
def iterativeSplit[T](iterO: Iterator[T])(breakOn: T => Boolean): Iterator[List[T]] =
new Iterator[List[T]] {
private var iter = iterO
def hasNext = iter.hasNext
def next = {
val (i1,i2) = iter.span(el => !breakOn(el))
val cur = i1.toList
iter = i2.dropWhile(breakOn)
cur
}
}.withFilter(l => l.nonEmpty)
e funziona bene su piccoli ingressi, ma sugli ingressi larges , questo funziona molto lenta, ed eccezione di overflow a volte vengo impilare
qui è il codice che ricrea il problema:
val iter = ("aaaaaaaaabbbbbbbbbbbccccccccccccc\r\n" * 10000).iterator
iterativeSplit(iter)(c => c == '\r' || c == '\n').length
l'analisi dello stack durante la corsa è:
...
at scala.collection.Iterator$$anon$1.hasNext(Iterator.scala:847)
at scala.collection.Iterator$$anon$19.hasNext(Iterator.scala:615)
at scala.collection.Iterator$$anon$1.hasNext(Iterator.scala:847)
at scala.collection.Iterator$$anon$18.hasNext(Iterator.scala:591)
at scala.collection.Iterator$$anon$1.hasNext(Iterator.scala:847)
at scala.collection.Iterator$$anon$19.hasNext(Iterator.scala:615)
at scala.collection.Iterator$$anon$1.hasNext(Iterator.scala:847)
at scala.collection.Iterator$$anon$18.hasNext(Iterator.scala:591)
at scala.collection.Iterator$$anon$1.hasNext(Iterator.scala:847)
at scala.collection.Iterator$$anon$19.hasNext(Iterator.scala:615)
at scala.collection.Iterator$$anon$1.hasNext(Iterator.scala:847)
at scala.collection.Iterator$$anon$18.hasNext(Iterator.scala:591)
at scala.collection.Iterator$$anon$1.hasNext(Iterator.scala:847)
...
guardando il codice sorgente (sto usando Scala 2.10.4) linea 591 è la hasNext
del secondo iteratore dalla span
, e la linea 651 è il hasNext
nel iteratore da dropWhile
Credo che sto utilizzando quei 2 iteratori in modo non corretto, ma non riesco a capire perché
Ben fatto, grazie. E ora anche il 'dropWhile' non è necessario poiché il filtro si prenderà cura degli elementi che si spezzano. – lev
Ho aggiornato la mia risposta, poiché mi sono reso conto che la mia soluzione originale utilizza tecniche fortemente scoraggiate nella documentazione. – DNA
Questo è grandioso, grazie! Per prevenire un errore durante l'uso di 'toList' sull'iter iter diviso, ho aggiunto' while (cercando && iter.hasNext) ' – ValD