Ich habe einen Iterator von Zeichenfolgen, wobei jede Zeichenfolge entweder "H"
(Header) oder "D"
(Detail) sein kann. Ich möchte diesen Iterator in Blöcke aufteilen, wobei jeder Block mit einem Header beginnt und 0 bis viele Details haben kann.
Ich weiß, wie man dieses Problem löst, indem man alles in den Speicher lädt. Zum Beispiel der folgende Code:
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
gibt 5 Blöcke zurück - List(List(H, D, D, D), List(H, D), List(H), List(H, D, D), List(H, D))
- was ich will.
Anstelle des List[List[String]]
Ergebnisses möchte ich jedoch eine Iterator[List[String]]
oder eine andere Struktur, mit der ich das Ergebnis träge auswerten und nicht die gesamte Eingabe in den Speicher laden kann, wenn der gesamte Iterator verbraucht ist. Ich möchte nur den Block in den Speicher laden, der verbraucht wird zu einem Zeitpunkt (zB: wenn ich anrufe iterator.next
).
Wie kann ich den obigen Code ändern, um das gewünschte Ergebnis zu erzielen?
EDIT: Ich brauche dies speziell in Scala 2.11, da die Umgebung, die ich benutze, daran festhält. Ich bin froh, auch Antworten für andere Versionen zu akzeptieren.
Antworten:
Hier ist die einfachste Implementierung, die ich finden konnte (generisch und faul):
benutze es so:
Hier ist die Spezifikation:
Scalafiddle mit Tests und zusätzlichen Kommentaren: https://scalafiddle.io/sf/q8xbQ9N/11
(Wenn die Antwort hilfreich ist, stimmen Sie bitte ab. Ich habe etwas zu viel Zeit damit verbracht :))
ZWEITE UMSETZUNG:
Sie haben eine Version vorgeschlagen , die nicht verwendet wird
sliding
. Hier ist es, aber es hat seine eigenen Probleme unten aufgeführt.Züge:
T>:Null
Typen. Wir müssen nur ein Element hinzufügen, das die letzte Sammlung am Ende schließt (null ist perfekt, aber es schränkt unseren Typ ein).Hier ist die Skalafiddle: https://scalafiddle.io/sf/q8xbQ9N/11
quelle
scanLeft
startGroup sammeln und sie nur einmal aufrufen, ohne die Länge zu überprüfen. Es ist beeindruckend, wie ich es vorher nicht lösen konnte und dank Ihrer Antwort kann ich jetzt sogar mögliche Optimierungen sehen. Vielen Dank!Wenn Sie Scala 2.13.x verwenden, können Sie eine neue erstellen,
Iterator
indem Sie sie über das Original entfaltenIterator
.testen:
quelle
Ich denke, die
scanLeft
Bedienung könnte in diesem Fall hilfreich sein, wenn Sie die Scala 2.11-Version verwenden möchten.Ich würde gerne die nächste Lösung finden, aber ich fürchte, sie sieht komplizierter aus als die ursprüngliche:
Typen hinzugefügt, zum Beispiel Lesbarkeit. Ich hoffe das hilft!
quelle