Ich verwende Ruby 1.8.6 mit Rails 1.2.3 und muss feststellen, ob zwei Arrays dieselben Elemente haben, unabhängig davon, ob sie in derselben Reihenfolge sind oder nicht. Eines der Arrays enthält garantiert keine Duplikate (das andere könnte, in diesem Fall lautet die Antwort nein).
Mein erster Gedanke war
require 'set'
a.to_set == b.to_set
aber ich habe mich gefragt, ob es einen effizienteren oder idiomatischeren Weg gibt, dies zu tun.
ruby
arrays
comparison
Taymon
quelle
quelle
[1,2]
und[2,1,1]
haben?)difference
eine Lösung eingeführt, die sowohl sehr schnell als auch gut lesbar ist. Mehr Infos hier.Antworten:
Dies erfordert keine Konvertierung, um Folgendes festzulegen:
quelle
.uniq.sort
dann? Außerdemuniq
ist ähnlich wieto_set
intern plus zusätzlich.to_a.sort
uniq
s. Eigentlich habe ich eines der Arrays mit erstelltRange#to_a
, also musste ich nursort
das andere.für zwei Arrays A und B: A und B haben den gleichen Inhalt, wenn:
(A-B).blank? and (B-A).blank?
oder Sie können einfach nachsehen:
((A-B) + (B-A)).blank?
Auch wie von @ cort3z vorgeschlagen, funktioniert diese Lösung auch für polymorphe Arrays, d. H.
::::::::::: BEARBEITEN ::::::::::::::
Wie in den Kommentaren vorgeschlagen, schlägt die obige Lösung für Duplikate fehl. Obwohl gemäß der Frage, die nicht einmal erforderlich ist, da der Fragesteller nicht an Duplikaten interessiert ist (er konvertiert seine Arrays vor dem Überprüfen in einen Satz und maskiert Duplikate und selbst wenn Sie sich diese ansehen Die akzeptierte Antwort verwendet er vor dem Überprüfen mit einem .uniq-Operator und maskiert auch Duplikate.). Wenn Sie dennoch an Duplikaten interessiert sind, wird dies durch Hinzufügen einer Überprüfung der Anzahl behoben (gemäß der Frage kann nur ein Array Duplikate enthalten). Die endgültige Lösung lautet also:
A.size == B.size and ((A-B) + (B-A)).blank?
quelle
A=[1]
undB=[1,1]
, beide(A-B)
und(B-A)
leer zurückgeben. Siehe Array-Dokumentation .a.to_set == b.to_set
und die akzeptierte Antwort verwendeta.uniq.sort == b.uniq.sort
und beide liefern genau das gleiche Ergebnis wie((A-B) + (B-A)).blank?
für A = [1]. und B = [1,1] stimmen überein? Da er nur um eine Verbesserung gegenüber seiner ursprünglichen Lösung gebeten hat, funktioniert meine ursprüngliche Lösung immer noch :). zustimmen?A = [123, "test", [], some_object, nil]
undB = A#because I am lazy
, dannA.uniq.sort
wird ein Fehler ausgegeben (Vergleich von Zeichenfolge und Array fehlgeschlagen).A = [1, 1, 2]
undB = [1, 2, 2]
Geschwindigkeitsvergleiche
quelle
sort
die Geschwindigkeitto_set
, eine Outperformance mit ausreichend großen Arrays zu erzielen, bei denen O (n logn) mehr zählt als der Aufwand, der erforderlich ist, um das Array in ein Set umzuwandelnRuby 2.6+
Ruby wird
difference
in 2.6 eingeführt.Dies ergibt hier eine sehr schnelle, sehr lesbare Lösung wie folgt:
Ausführen der Benchmarks:
Hoffe das hilft jemandem!
quelle
Wenn die Elemente von
a
undb
sindComparable
,Korrektur der Antwort von @ mori basierend auf dem Kommentar von @ steenslag
quelle
a
undb
kann sortiert werden.Wenn Sie erwarten,
[:a, :b] != [:a, :a, :b]
to_set
funktioniert nicht. Sie können stattdessen die Frequenz verwenden:quelle
a.sort == b.sort
wenn ihm die Frequenz am Herzen liegt?["", :b].frequency == [:b, ""].frequency #=> true
a.group_by{|i| i} == b.group_by{|i| i}
Wenn Sie wissen, dass die Arrays gleich lang sind und keines der Arrays Duplikate enthält, funktioniert dies auch:
Erläuterung:
&
In diesem Fall gibt der Operator eine Kopie von a1 ohne alle in a2 nicht gefundenen Elemente zurück. Dies entspricht dem Original a1, wenn beide Arrays denselben Inhalt ohne Duplikate haben.Analyse: Da die Reihenfolge unverändert ist, wird dies vermutlich als Doppeliteration implementiert, die so konsistent ist
O(n*n)
, insbesondere bei großen Arrays,a1.sort == a2.sort
die im schlimmsten Fall schlechter abschneiden solltenO(n*logn)
.quelle
a1 = [1,2,3], a2 = [2, 1, 3]
a1 && a2
kehrt[2,1,3]
für mich zurück, was nicht gleich ista1
a1==a2
? Es mag funktionieren, wennarray1
auf der rechten Seite die Gleichheit durch ersetzt wirdarray2
, aber ich bezweifle, dass die Reihenfolge der zurückgegebenen Elemente&
garantiert ist.&
ist ein festgelegter Schnittpunktoperator für Arrays,&&
ist logisch UND - sie sind sehr unterschiedlich!Ein Ansatz besteht darin, das Array ohne Duplikate zu durchlaufen
Dies gibt ein Array von Wahrheiten zurück. Wenn false angezeigt wird, gibt das äußere
include?
true zurück. Sie müssen also das Ganze umkehren, um festzustellen, ob es sich um eine Übereinstimmung handelt.quelle
kombinieren
&
undsize
kann auch schnell sein.quelle