Tengo un iterador de cadenas, donde cada cadena puede ser "H"
(encabezado) o "D"
(detalle). Quiero dividir este iterador en bloques, donde cada bloque comienza con un encabezado y puede tener de 0 a muchos detalles.
Sé cómo resolver este problema cargando todo en la memoria. Por ejemplo, el siguiente código:
Seq("H","D","D","D","H","D","H","H","D","D","H","D").toIterator
.foldLeft(List[List[String]]())((acc, x) => x match {
case "H" => List(x) :: acc
case "D" => (x :: acc.head) :: acc.tail })
.map(_.reverse)
.reverse
devuelve 5 bloques, List(List(H, D, D, D), List(H, D), List(H), List(H, D, D), List(H, D))
que es lo que quiero.
Sin embargo, en lugar de List[List[String]]
en el resultado, quiero una Iterator[List[String]]
u otra estructura que me permita evaluar el resultado de forma perezosa y no cargar toda la entrada en la memoria si se consume todo el iterador , quiero cargar en la memoria solo el bloque que se consume a la vez (por ejemplo: cuando llamo iterator.next
).
¿Cómo puedo modificar el código anterior para lograr el resultado que quiero?
EDITAR: Necesito esto en Scala 2.11 específicamente, ya que el entorno que uso se adhiere a él. Sin embargo, me alegro de aceptar también respuestas para otras versiones.
Respuestas:
Aquí está la implementación más simple que pude encontrar (es genérica y perezosa):
úsalo así:
Aquí está la especificación:
scalafiddle con pruebas y comentarios adicionales: https://scalafiddle.io/sf/q8xbQ9N/11
(si la respuesta es útil, vote por favor, por favor. Pasé demasiado tiempo :))
SEGUNDA APLICACIÓN:
Tiene una versión propuesta que no utiliza
sliding
. Aquí está, pero tiene sus propios problemas enumerados a continuación.Rasgos:
T>:Null
tipos. Solo necesitamos agregar un elemento que cierre la última colección al final (nulo es perfecto pero limita nuestro tipo).Aquí está scalafiddle: https://scalafiddle.io/sf/q8xbQ9N/11
fuente
scanLeft
y llamar a startGroup solo una vez, sin verificar la longitud. Es impresionante cómo no pude resolverlo antes y gracias a su respuesta ahora incluso puedo ver posibles optimizaciones. ¡Gracias!Si está utilizando Scala 2.13.x, puede crear uno nuevo
Iterator
desplegando sobre el originalIterator
.pruebas:
fuente
Creo que la
scanLeft
operación podría ayudar en este caso, si desea utilizar la versión Scala 2.11.Me gustaría proponer la próxima solución, pero me temo que parece más complicada que la original:
Tipos añadidos, por ejemplo, legibilidad. ¡Espero que esto ayude!
fuente