@JanDvorak Bei dieser Frage geht es nicht nur um die Rückgabe von Subhash, sondern auch um die Änderung eines vorhandenen. Sehr ähnliche Dinge, aber ActiveSupport hat verschiedene Mittel, um damit umzugehen.
Skalee
Antworten:
58
Wenn Sie speziell möchten, dass die Methode die extrahierten Elemente zurückgibt, h1 jedoch gleich bleibt:
Dies ist O (n2) - Sie haben eine Schleife auf der Auswahl, eine andere Schleife auf dem Include, die h1.size times genannt wird.
Metakung Fu
1
Während diese Antwort für reinen Rubin anständig ist, ist die folgende Antwort (mit eingebauten sliceoder except, abhängig von Ihren Bedürfnissen) viel sauberer
Krease
137
ActiveSupportZumindest seit 2.3.8 stellt vier praktische Möglichkeiten: #slice, #exceptsowie deren Pendants destruktive: #slice!und #except!. Sie wurden in anderen Antworten erwähnt, aber um sie an einer Stelle zusammenzufassen:
Beachten Sie die Rückgabewerte der Bang-Methoden. Sie passen nicht nur vorhandenen Hash an, sondern geben auch entfernte (nicht beibehaltene) Einträge zurück. Das Hash#except!passt am besten zum Beispiel in der Frage:
ActiveSupportbenötigt keine ganzen Schienen, ist ziemlich leicht. Tatsächlich hängen viele Edelsteine, die keine Schienen sind, davon ab, sodass Sie sie höchstwahrscheinlich bereits in Gemfile.lock haben. Sie müssen die Hash-Klasse nicht selbst erweitern.
Mokey Patching ist definitiv der richtige Weg für IMO. Viel sauberer und macht die Absicht klarer.
Romário
1
Hinzufügen, um den Code zu ändern, um das Kernmodul korrekt zu adressieren, das Modul zu definieren und das erweiterte Hash-Kern-Modul zu importieren Ende Hash.include CoreExtensions :: Hash
Ich denke, Sie beschreiben Auszug!. Extrakt! Entfernt die Schlüssel aus dem anfänglichen Hash und gibt einen neuen Hash zurück, der die entfernten Schlüssel enthält. Scheibe! macht das Gegenteil: Entfernen Sie alle bis auf die angegebenen Schlüssel aus dem anfänglichen Hash (und geben Sie erneut einen neuen Hash zurück, der die entfernten Schlüssel enthält). Also in Scheiben schneiden! ist ein bisschen mehr wie eine "Beibehaltungs" -Operation.
Gut gemacht. Nicht ganz das, wonach er fragt. Ihre Methode gibt Folgendes zurück: {: d =>: D ,: b =>: B ,: e => nil ,: f => nil} {: c =>: C ,: a =>: A ,: d => : D ,: b =>: B}
Andy
Eine äquivalente einzeilige (und möglicherweise schnellere) Lösung: <pre> def subhash(*keys) select {|k,v| keys.include?(k)} end
Hier ist eine funktionale Lösung, die nützlich sein kann, wenn Sie nicht mit Ruby 2.5 arbeiten und Ihre Hash-Klasse nicht durch Hinzufügen einer neuen Methode verschmutzen möchten:
Nur eine Ergänzung zur Slice-Methode: Wenn die Subhash-Schlüssel, die Sie vom ursprünglichen Hash trennen möchten, dynamisch sind, können Sie Folgendes tun:
slice(*dynamic_keys)# dynamic_keys should be an array type
Wir können dies tun, indem wir nur die Schlüssel schleifen, die wir extrahieren möchten, und nur überprüfen, ob der Schlüssel vorhanden ist, und ihn dann extrahieren.
Antworten:
Wenn Sie speziell möchten, dass die Methode die extrahierten Elemente zurückgibt, h1 jedoch gleich bleibt:
Und wenn Sie das in die Hash-Klasse patchen möchten:
Wenn Sie nur die angegebenen Elemente aus dem Hash entfernen möchten, ist dies mit delete_if viel einfacher .
quelle
slice
oderexcept
, abhängig von Ihren Bedürfnissen) viel saubererActiveSupport
Zumindest seit 2.3.8 stellt vier praktische Möglichkeiten:#slice
,#except
sowie deren Pendants destruktive:#slice!
und#except!
. Sie wurden in anderen Antworten erwähnt, aber um sie an einer Stelle zusammenzufassen:Beachten Sie die Rückgabewerte der Bang-Methoden. Sie passen nicht nur vorhandenen Hash an, sondern geben auch entfernte (nicht beibehaltene) Einträge zurück. Das
Hash#except!
passt am besten zum Beispiel in der Frage:ActiveSupport
benötigt keine ganzen Schienen, ist ziemlich leicht. Tatsächlich hängen viele Edelsteine, die keine Schienen sind, davon ab, sodass Sie sie höchstwahrscheinlich bereits in Gemfile.lock haben. Sie müssen die Hash-Klasse nicht selbst erweitern.quelle
x.except!(:c, :d)
(mit Knall) sollte sein# => {:a=>1, :b=>2}
. Gut, wenn Sie Ihre Antwort bearbeiten können.Wenn Sie Schienen verwenden , ist Hash # Slice der richtige Weg.
Wenn Sie keine Schienen verwenden , gibt Hash # values_at die Werte in derselben Reihenfolge zurück, in der Sie sie gefragt haben, damit Sie Folgendes tun können:
Ex:
Erläuterung:
Raus
{:a => 1, :b => 2, :c => 3}
wollen wir{:a => 1, :b => 2}
Wenn Sie der Meinung sind, dass das Patchen von Affen der richtige Weg ist, möchten Sie Folgendes:
quelle
Ruby 2.5 hat Hash # Slice hinzugefügt :
quelle
Sie können Slice! (* -Tasten) verwenden, die in den Kernerweiterungen von ActiveSupport verfügbar sind
initial_hash wäre jetzt
extract_slide wäre jetzt
Sie können anschauen
slice.rb in ActiveSupport 3.1.3
quelle
quelle
def subhash(*keys) select {|k,v| keys.include?(k)} end
quelle
Wenn Sie Schienen verwenden, kann es zweckmäßig sein, Hash.except zu verwenden
quelle
quelle
Hier ist ein schneller Leistungsvergleich der vorgeschlagenen Methoden,
#select
scheint der schnellste zu seinDie Verfeinerung wird folgendermaßen aussehen:
Und um es zu benutzen:
quelle
Beide
delete_if
undkeep_if
sind Teil des Ruby-Kerns. Hier können Sie erreichen, was Sie möchten, ohne denHash
Typ zu patchen .Weitere Informationen finden Sie unter den folgenden Links in der Dokumentation:
quelle
Wie bereits erwähnt, hat Ruby 2.5 die Hash # -Slice-Methode hinzugefügt.
Rails 5.2.0beta1 hat auch eine eigene Version von Hash # Slice hinzugefügt, um die Funktionalität für Benutzer des Frameworks zu verbessern, die eine frühere Version von Ruby verwenden. https://github.com/rails/rails/commit/01ae39660243bc5f0a986e20f9c9bff312b1b5f8
Wenn Sie aus irgendeinem Grund Ihre eigenen implementieren möchten, ist dies auch ein guter Einzeiler:
quelle
Dieser Code fügt die von Ihnen angeforderte Funktionalität in die Hash-Klasse ein:
und erzeugt die von Ihnen angegebenen Ergebnisse:
Hinweis: Diese Methode gibt tatsächlich die extrahierten Schlüssel / Werte zurück.
quelle
Hier ist eine funktionale Lösung, die nützlich sein kann, wenn Sie nicht mit Ruby 2.5 arbeiten und Ihre Hash-Klasse nicht durch Hinzufügen einer neuen Methode verschmutzen möchten:
Dann können Sie es auch auf verschachtelte Hashes anwenden:
quelle
Nur eine Ergänzung zur Slice-Methode: Wenn die Subhash-Schlüssel, die Sie vom ursprünglichen Hash trennen möchten, dynamisch sind, können Sie Folgendes tun:
quelle
Wir können dies tun, indem wir nur die Schlüssel schleifen, die wir extrahieren möchten, und nur überprüfen, ob der Schlüssel vorhanden ist, und ihn dann extrahieren.
quelle