So fügen Sie Hash I do ein neues Paar hinzu:
{:a => 1, :b => 2}.merge!({:c => 3}) #=> {:a => 1, :b => 2, :c => 3}
Gibt es eine ähnliche Möglichkeit, einen Schlüssel aus Hash zu löschen?
Das funktioniert:
{:a => 1, :b => 2}.reject! { |k| k == :a } #=> {:b => 2}
aber ich würde folgendes erwarten:
{:a => 1, :b => 2}.delete!(:a) #=> {:b => 2}
Es ist wichtig, dass der Rückgabewert der verbleibende Hash ist, damit ich folgende Dinge tun kann:
foo(my_hash.reject! { |k| k == my_key })
in einer Zeile.
Rails hat eine except/except! -Methode , die den Hash mit den entfernten Schlüsseln zurückgibt. Wenn Sie Rails bereits verwenden, macht es keinen Sinn, eine eigene Version davon zu erstellen.
class Hash
# Returns a hash that includes everything but the given keys.
# hash = { a: true, b: false, c: nil}
# hash.except(:c) # => { a: true, b: false}
# hash # => { a: true, b: false, c: nil}
#
# This is useful for limiting a set of parameters to everything but a few known toggles:
# @person.update(params[:person].except(:admin))
def except(*keys)
dup.except!(*keys)
end
# Replaces the hash without the given keys.
# hash = { a: true, b: false, c: nil}
# hash.except!(:c) # => { a: true, b: false}
# hash # => { a: true, b: false }
def except!(*keys)
keys.each { |key| delete(key) }
self
end
end
Oneliner Ruby, es funktioniert nur mit Ruby> 1.9.x:
1.9.3p0 :002 > h = {:a => 1, :b => 2}
=> {:a=>1, :b=>2}
1.9.3p0 :003 > h.tap { |hs| hs.delete(:a) }
=> {:b=>2}
Tap Methode gibt immer das Objekt zurück, auf das zugegriffen wird ...
Andernfalls können Sie, wenn Sie active_support/core_ext/hash
(der in jeder Rails -Anwendung automatisch erforderlich ist) angefordert haben, je nach Ihren Anforderungen eine der folgenden Methoden anwenden:
➜ ~ irb
1.9.3p125 :001 > require 'active_support/core_ext/hash' => true
1.9.3p125 :002 > h = {:a => 1, :b => 2, :c => 3}
=> {:a=>1, :b=>2, :c=>3}
1.9.3p125 :003 > h.except(:a)
=> {:b=>2, :c=>3}
1.9.3p125 :004 > h.slice(:a)
=> {:a=>1}
ausgenommen verwendet einen Blacklist-Ansatz, sodass alle als Argumente aufgelisteten Schlüssel entfernt werden, während Slice einen Whitelist-Ansatz verwendet, sodass alle Schlüssel entfernt werden, die nicht als Argumente aufgeführt sind. Es gibt auch die BANG-Version dieser Methoden (except!
und slice!
), die den angegebenen Hash modifizieren, deren Rückgabewert jedoch unterschiedlich ist. Beide geben einen Hash zurück. Es stellt die entfernten Schlüssel für slice!
und die Schlüssel dar, die für except!
aufbewahrt werden:
1.9.3p125 :011 > {:a => 1, :b => 2, :c => 3}.except!(:a)
=> {:b=>2, :c=>3}
1.9.3p125 :012 > {:a => 1, :b => 2, :c => 3}.slice!(:a)
=> {:b=>2, :c=>3}
Warum nicht einfach:
hash.delete(key)
Es gibt viele Möglichkeiten, einen Schlüssel aus einem Hash zu entfernen und den verbleibenden Hash in Ruby abzurufen.
.slice
=> Ausgewählte Schlüssel werden zurückgegeben und nicht aus dem ursprünglichen Hash gelöscht. Verwenden Sie slice!
, wenn Sie die Schlüssel dauerhaft entfernen möchten, andernfalls verwenden Sie einfach slice
.
2.2.2 :074 > hash = {"one"=>1, "two"=>2, "three"=>3}
=> {"one"=>1, "two"=>2, "three"=>3}
2.2.2 :075 > hash.slice("one","two")
=> {"one"=>1, "two"=>2}
2.2.2 :076 > hash
=> {"one"=>1, "two"=>2, "three"=>3}
.delete
=> Löscht die ausgewählten Schlüssel aus dem ursprünglichen Hash (es kann nur einen Schlüssel und nicht mehr als einen akzeptieren).
2.2.2 :094 > hash = {"one"=>1, "two"=>2, "three"=>3}
=> {"one"=>1, "two"=>2, "three"=>3}
2.2.2 :095 > hash.delete("one")
=> 1
2.2.2 :096 > hash
=> {"two"=>2, "three"=>3}
.except
=> Die verbleibenden Schlüssel werden zurückgegeben, es wird jedoch nichts aus dem ursprünglichen Hash gelöscht. Verwenden Sie except!
, wenn Sie die Schlüssel dauerhaft entfernen möchten, andernfalls verwenden Sie einfach except
.
2.2.2 :097 > hash = {"one"=>1, "two"=>2, "three"=>3}
=> {"one"=>1, "two"=>2, "three"=>3}
2.2.2 :098 > hash.except("one","two")
=> {"three"=>3}
2.2.2 :099 > hash
=> {"one"=>1, "two"=>2, "three"=>3}
.delete_if
=> Falls Sie einen Schlüssel basierend auf einem Wert entfernen müssen. Es werden offensichtlich die passenden Schlüssel aus dem ursprünglichen Hash entfernt.
2.2.2 :115 > hash = {"one"=>1, "two"=>2, "three"=>3, "one_again"=>1}
=> {"one"=>1, "two"=>2, "three"=>3, "one_again"=>1}
2.2.2 :116 > value = 1
=> 1
2.2.2 :117 > hash.delete_if { |k,v| v == value }
=> {"two"=>2, "three"=>3}
2.2.2 :118 > hash
=> {"two"=>2, "three"=>3}
.compact
=> Hiermit werden alle nil
Werte aus dem Hash entfernt. Verwenden Sie compact!
, wenn Sie die nil
Werte dauerhaft entfernen möchten, andernfalls verwenden Sie einfach compact
.
2.2.2 :119 > hash = {"one"=>1, "two"=>2, "three"=>3, "nothing"=>nil, "no_value"=>nil}
=> {"one"=>1, "two"=>2, "three"=>3, "nothing"=>nil, "no_value"=>nil}
2.2.2 :120 > hash.compact
=> {"one"=>1, "two"=>2, "three"=>3}
Ergebnisse basierend auf Ruby 2.2.2.
Wenn Sie pure Ruby (keine Rails) verwenden möchten, möchten Sie keine Erweiterungsmethoden erstellen (möglicherweise benötigen Sie diese nur an ein oder zwei Stellen und möchten den Namespace nicht mit unzähligen Methoden verschmutzen). und Sie möchten kein Hash an Ort und Stelle bearbeiten (dh Sie sind ein Fan von funktionaler Programmierung wie ich), können Sie Folgendes auswählen:
>> x = {:a => 1, :b => 2, :c => 3}
=> {:a=>1, :b=>2, :c=>3}
>> x.select{|x| x != :a}
=> {:b=>2, :c=>3}
>> x.select{|x| ![:a, :b].include?(x)}
=> {:c=>3}
>> x
=> {:a=>1, :b=>2, :c=>3}
#in lib/core_extensions.rb
class Hash
#pass single or array of keys, which will be removed, returning the remaining hash
def remove!(*keys)
keys.each{|key| self.delete(key) }
self
end
#non-destructive version
def remove(*keys)
self.dup.remove!(*keys)
end
end
#in config/initializers/app_environment.rb (or anywhere in config/initializers)
require 'core_extensions'
Ich habe dies so eingerichtet, dass .remove eine Kopie des Hashes mit entfernten Schlüsseln zurückgibt, während remove! ändert den Hash selbst. Dies entspricht den Ruby Konventionen. zB von der Konsole
>> hash = {:a => 1, :b => 2}
=> {:b=>2, :a=>1}
>> hash.remove(:a)
=> {:b=>2}
>> hash
=> {:b=>2, :a=>1}
>> hash.remove!(:a)
=> {:b=>2}
>> hash
=> {:b=>2}
>> hash.remove!(:a, :b)
=> {}
Sie können except!
aus dem Edelstein facets
verwenden:
>> require 'facets' # or require 'facets/hash/except'
=> true
>> {:a => 1, :b => 2}.except(:a)
=> {:b=>2}
Der ursprüngliche Hash ändert sich nicht.
BEARBEITEN: Wie Russel sagt, haben Facetten einige versteckte Probleme und sind nicht vollständig API-kompatibel mit ActiveSupport. Andererseits ist ActiveSupport nicht so vollständig wie Facetten. Am Ende würde ich AS verwenden und die Edge-Fälle in Ihrem Code belassen.
Anstatt Affen zu patchen oder unnötigerweise große Bibliotheken einzuschließen, können Sie Verfeinerungen, wenn Sie Ruby 2 verwenden :
module HashExtensions
refine Hash do
def except!(*candidates)
candidates.each { |candidate| delete(candidate) }
self
end
def except(*candidates)
dup.remove!(candidates)
end
end
end
Sie können diese Funktion verwenden, ohne andere Teile Ihres Programms zu beeinträchtigen oder große externe Bibliotheken einbeziehen zu müssen.
class FabulousCode
using HashExtensions
def incredible_stuff
delightful_hash.except(:not_fabulous_key)
end
end
in reinem Rubin:
{:a => 1, :b => 2}.tap{|x| x.delete(:a)} # => {:b=>2}
Siehe Ruby on Rails: Löschen mehrerer Hash-Schlüssel
hash.delete_if{ |k,| keys_to_delete.include? k }
Es war großartig, wenn delete das Löschpaar des Hash zurückgibt. Ich mache das:
hash = {a: 1, b: 2, c: 3}
{b: hash.delete(:b)} # => {:b=>2}
hash # => {:a=>1, :c=>3}
Dies ist eine einzeilige Methode, die jedoch nicht gut lesbar ist. Es wird empfohlen, stattdessen zwei Zeilen zu verwenden.
use_remaining_hash_for_something(Proc.new { hash.delete(:key); hash }.call)
Mehrere Möglichkeiten zum Löschen von Key in Hash. Sie können jede Methode von unten verwenden
hash = {a: 1, b: 2, c: 3}
hash.except!(:a) # Will remove *a* and return HASH
hash # Output :- {b: 2, c: 3}
hash = {a: 1, b: 2, c: 3}
hash.delete(:a) # will remove *a* and return 1 if *a* not present than return nil
So viele Möglichkeiten gibt es, können Sie Ruby doc von Hash hier .
Danke