Ich habe zwei lange Zahlenströme aus zwei verschiedenen Quellen (Binärdaten) in Ruby (1.9.2).
Die beiden Quellen sind in Form von zwei Enumeratoren gekapselt.
Ich möchte überprüfen, dass die beiden Streams genau gleich sind.
Ich bin mit ein paar Lösungen gekommen, aber beide scheinen ziemlich unelegant.
Der erste transformiert beide einfach in ein Array:
%Vor%Das funktioniert, aber es ist nicht besonders leistungsfähig, besonders wenn die Streams viel Information haben.
Die andere Option ist ... ugh.
%Vor%Also, gibt es einen einfacheren, eleganteren Weg, dies zu tun?
Ein Element nach dem anderen zu vergleichen, ist wahrscheinlich das Beste, was Sie tun können, aber Sie können es besser machen als Ihre "ugh" -Lösung:
%Vor% Der schwierigste Teil ist die Unterscheidung zwischen nur einem auslaufenden und einem auslaufenden Stream. Das Einfügen der StopIteration
-Ausnahme in eine separate Funktion und die Verwendung des Fehlens eines Schlüssels in einem Hash ist eine ziemlich bequeme Möglichkeit, dies zu tun. Wenn Sie vals[:s1]
nur überprüfen, treten Probleme auf, wenn Ihr Stream false
oder nil
enthält. Das Vorhandensein eines Schlüssels wird jedoch durch das Überprüfen dieses Problems behoben.
Hier ist eine Aufnahme, indem Sie eine Alternative für Enumerable#zip
erstellen, die träge arbeitet und kein ganzes Array erstellt. Es kombiniert meine Implementierung von Closures interleave
und anderen zwei Antworten hier (mit Sentinel-Wert, um das Ende des% anzuzeigen co_de% wurde erreicht - die Tatsache, die das Problem verursacht, ist, dass Enumerable
die next
zurückspult, sobald sie das Ende erreicht hat.
Diese Lösung unterstützt mehrere Parameter, sodass Sie n -Strukturen gleichzeitig vergleichen können.
%Vor% Wenn Sie also eine Variante von Enumerable
haben, die träge funktioniert und die Iteration nicht stoppt, wenn das erste Enumerable das Ende erreicht, können Sie mit zip
oder all?
die entsprechenden Elemente auf Gleichheit prüfen.
Nach der Diskussion in den Kommentaren, hier ist zip-basierte Lösung, erste umhüllende Block-Version von zip
innerhalb einer Enumerator
, und dann verwenden, um entsprechende Elemente zu vergleichen.
Es funktioniert, aber Randfall ist bereits erwähnt: Wenn der erste Strom kürzer ist als der andere, werden die restlichen Elemente aus dem anderen entfernt (siehe Beispiel unten).
Ich habe diese Antwort als Community-Wiki markiert, da andere Mitglieder dies verbessern könnten.
%Vor%Hier ist ein 2-Quellen-Beispiel, das eine Fiber / Co-Routine verwendet. Es ist ein bisschen langatmig, aber es ist sehr deutlich über sein Verhalten, das ist nett.
%Vor%Tags und Links ruby enumerator