ruby-on-rails tableau - Comment supprimer une clé de Hash et obtenir le hachage restant dans Ruby / Rails?




dimensions array (11)

Si vous voulez utiliser du Ruby pur (sans Rails), vous ne voulez pas créer de méthodes d'extension (peut-être vous n'en avez besoin qu'à un ou deux endroits et ne voulez pas polluer l'espace de noms avec des tonnes de méthodes) et vous ne voulez pas modifier le hachage en place (c'est-à-dire, 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}

Pour ajouter une nouvelle paire à Hash je fais:

{:a => 1, :b => 2}.merge!({:c => 3})   #=> {:a => 1, :b => 2, :c => 3}

Existe-t-il une manière similaire de supprimer une clé de Hash?

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 retournée soit le hash restant, donc je pourrais faire des choses comme:

foo(my_hash.reject! { |k| k == my_key })

en une ligne.


Vous pouvez utiliser except! à partir de la 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 API avec ActiveSupport. De l'autre côté, ActiveSupport n'est pas aussi complet que les facettes. À la fin, j'utiliserais AS et laisserais les cas de bord dans votre code.


C'est une façon de faire, mais ce n'est pas très lisible. Recommande d'utiliser deux lignes à la place.

use_remaining_hash_for_something(Proc.new { hash.delete(:key); hash }.call)

Il y a plusieurs façons de retirer une clé d'un hachage et d'obtenir le hachage restant dans Ruby.

  1. .slice => Il retournera les clés sélectionnées et ne les supprimera pas du hash d'origine

    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} 
    
  2. .delete => Il va supprimer les clés sélectionnées du hash d'origine (il ne peut accepter qu'une seule clé 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} 
    
  3. .except => Il retournera les clés restantes mais ne supprimera rien du hash d'origine

    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}         
    
  4. .delete_if => Au cas où vous devriez enlever une clé basée sur une valeur. Il va évidemment supprimer 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} 
    

Résultats basés sur Ruby 2.2.2.


en pur Ruby:

{:a => 1, :b => 2}.tap{|x| x.delete(:a)}   # => {:b=>2}

Pourquoi ne pas simplement utiliser:

hash.delete(key)

Rails a un sauf / sauf! méthode qui renvoie le hachage avec ces clés supprimées. Si vous utilisez déjà Rails, il n'y a aucun sens à créer votre propre version de cela.

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


#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 mis ceci en place pour que .remove renvoie une copie du hachage avec les clés retirées, alors que remove! modifie le hachage lui-même. Ceci est en accord avec les conventions de rubis. par exemple, à partir de 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)
=> {}

Cela fonctionnerait aussi: hash[hey] = nil


plage = 10..50

rand (plage)

ou

range.to_a.sample

ou

range.to_a.shuffle (ceci va mélanger le tableau entier et vous pouvez choisir un nombre aléatoire en premier ou en dernier ou n'importe quel de ce tableau pour en choisir un au hasard)





ruby-on-rails ruby ruby-on-rails-3 hashmap ruby-hash