Pour ajouter une nouvelle paire à Hash I do:
{:a => 1, :b => 2}.merge!({:c => 3}) #=> {:a => 1, :b => 2, :c => 3}
Existe-t-il une méthode similaire pour supprimer une clé de hachage?
Cela marche:
{:a => 1, :b => 2}.reject! { |k| k == :a } #=> {:b => 2}
mais je m'attendrais à avoir quelque chose comme:
{:a => 1, :b => 2}.delete!(:a) #=> {:b => 2}
Il est important que la valeur renvoyée soit le hachage restant afin que je puisse faire des choses comme:
foo(my_hash.reject! { |k| k == my_key })
dans une ligne.
Rails a une méthode except/except! qui renvoie le hachage avec ces clés supprimées. Si vous utilisez déjà Rails, il ne sert à rien de créer votre propre version.
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 uni Ruby, il ne fonctionne qu'avec 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 la méthode retourne toujours l'objet sur lequel est invoqué ...
Sinon, si vous avez requis active_support/core_ext/hash
(qui est automatiquement requis dans chaque application Rails], vous pouvez utiliser l'une des méthodes suivantes, en fonction de vos besoins:
➜ ~ 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}
excepté utilise une approche de liste noire, de sorte qu'il supprime toutes les clés répertoriées comme arguments, tandis que slice utilise une approche de liste blanche, de sorte qu'il supprime toutes les clés non répertoriées comme arguments. Il existe également la version bang de ces méthodes (except!
et slice!
) qui modifient le hachage donné mais dont la valeur de retour est différente, et qui retournent un hachage. Il représente les clés supprimées pour slice!
et les clés conservées pour le except!
:
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}
Pourquoi ne pas simplement utiliser:
hash.delete(key)
Il existe de nombreuses façons de supprimer une clé d'un hachage et d'obtenir le hachage restant en Ruby.
.slice
=> Il retournera les clés sélectionnées et ne les supprimera pas du hachage d'origine. Utilisez slice!
si vous souhaitez supprimer définitivement les clés, sinon utilisez la méthode simple 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
=> Il supprimera les clés sélectionnées du hachage d'origine (il ne peut en accepter qu'une seule et pas plus d'une).
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
=> Il retournera les clés restantes mais ne supprimera rien du hachage d'origine. Utilisez except!
si vous souhaitez supprimer définitivement les clés, sinon utilisez la méthode simple 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
=> Si vous devez supprimer une clé basée sur une valeur. Cela supprimera évidemment les clés correspondantes du hachage d'origine.
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
=> Il est utilisé pour supprimer toutes les valeurs nil
du hachage. Utilisez compact!
si vous souhaitez supprimer définitivement les valeurs nil
, sinon utilisez la méthode simple 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}
Résultats basés sur Ruby 2.2.2.
Si vous voulez utiliser pure Ruby (sans Rails), ne voulez pas créer de méthodes d'extension (vous n'avez peut-être besoin de cela que dans un ou deux endroits et vous ne voulez pas polluer l'espace de noms avec des tonnes de méthodes) et vous ne voulez pas éditer le hachage en place (vous êtes fan de la programmation fonctionnelle comme moi), vous pouvez "sélectionner":
>> 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'
J'ai configuré cela pour que .remove retourne une copie du hachage avec les clés retirées, en supprimant! modifie le hash lui-même. Ceci est conforme aux conventions Ruby. par exemple, depuis la console
>> 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)
=> {}
Vous pouvez utiliser except!
à partir du facets
gem:
>> require 'facets' # or require 'facets/hash/except'
=> true
>> {:a => 1, :b => 2}.except(:a)
=> {:b=>2}
Le hachage d'origine ne change pas.
EDIT: comme le dit Russel, les facettes ont des problèmes cachés et ne sont pas complètement compatibles avec les API avec ActiveSupport. De l’autre côté, ActiveSupport n’est pas aussi complet que les facettes. En fin de compte, j'utiliserais AS et laisserais Edge figurer dans votre code.
Au lieu d'appliquer des correctifs pour les singes ou d'inclure inutilement de grandes bibliothèques, vous pouvez utiliser raffinements si vous utilisez Ruby 2 :
module HashExtensions
refine Hash do
def except!(*candidates)
candidates.each { |candidate| delete(candidate) }
self
end
def except(*candidates)
dup.remove!(candidates)
end
end
end
Vous pouvez utiliser cette fonctionnalité sans affecter d'autres parties de votre programme, ni avoir à inclure de grandes bibliothèques externes.
class FabulousCode
using HashExtensions
def incredible_stuff
delightful_hash.except(:not_fabulous_key)
end
end
en rubis pur:
{:a => 1, :b => 2}.tap{|x| x.delete(:a)} # => {:b=>2}
Voir Ruby on Rails: Supprimer plusieurs clés de hachage
hash.delete_if{ |k,| keys_to_delete.include? k }
C'était génial si delete renvoie la paire de suppression du hachage. Je fais ça:
hash = {a: 1, b: 2, c: 3}
{b: hash.delete(:b)} # => {:b=>2}
hash # => {:a=>1, :c=>3}
C'est une façon de faire une ligne, mais ce n'est pas très lisible. Recommandez d'utiliser deux lignes à la place.
use_remaining_hash_for_something(Proc.new { hash.delete(:key); hash }.call)
Plusieurs façons de supprimer Key in Hash. vous pouvez utiliser n'importe quelle méthode ci-dessous
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
Il y a tant de façons, vous pouvez regarder sur Ruby doc de Hash ici .
Je vous remercie