110 votes

Comment extraire un sous-hachage d'un hachage ?

J'ai un hash :

h1 = {:a => :A, :b => :B, :c => :C, :d => :D}

Quelle est la meilleure façon d'extraire un sous-réseau comme celui-ci ?

h1.extract_subhash(:b, :d, :e, :f) # => {:b => :B, :d => :D}
h1 #=> {:a => :A, :c => :C}

5 votes

Note complémentaire : apidock.com/rails/Hash/slice%21

1 votes

@JanDvorak Cette question ne concerne pas seulement le retour d'un subhash mais aussi la modification d'un subhash existant. Ce sont des choses très similaires mais ActiveSupport a des moyens différents pour les traiter.

5voto

Ryan LeCompte Points 1784
module HashExtensions
  def subhash(*keys)
    keys = keys.select { |k| key?(k) }
    Hash[keys.zip(values_at(*keys))]
  end
end

Hash.send(:include, HashExtensions)

{:a => :A, :b => :B, :c => :C, :d => :D}.subhash(:a) # => {:a => :A}

1 votes

Beau travail. Pas tout à fait ce qu'il demande. Ta méthode renvoie : {:d=>:D, :b=>:B, :e=>nil, :f=>nil} {:c=>:C, :a=>:A, :d=>:D, :b=>:B}

0 votes

Une solution équivalente en une ligne (et peut-être plus rapide):<pre> def subhash(*keys) select {|k,v| keys.include?(k)} end

4voto

Cary Swoveland Points 6784
h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
keys = [:b, :d, :e, :f]

h2 = (h1.keys & keys).each_with_object({}) { |k,h| h.update(k=>h1.delete(k)) }
  #=> {:b => :B, :d => :D}
h1
  #=> {:a => :A, :c => :C}

3voto

Mark Points 653

Les deux sites delete_if et keep_if font partie du noyau de Ruby. Ici, vous pouvez réaliser ce que vous souhaitez sans Parcheando la Hash type.

h1 = {:a => :A, :b => :B, :c => :C, :d => :D}
h2 = h1.clone
p h1.keep_if { |key| [:b, :d, :e, :f].include?(key) } # => {:b => :B, :d => :D}
p h2.delete_if { |key, value| [:b, :d, :e, :f].include?(key) } #=> {:a => :A, :c => :C}

Pour plus d'informations, consultez les liens ci-dessous dans la documentation :

2voto

gayavat Points 3169

Si vous utilisez des rails, il peut être pratique d'utiliser Hash.except

h = {a:1, b:2}
h1 = h.except(:a) # {b:2}

2voto

josh Points 174

Comme d'autres l'ont mentionné, Ruby 2.5 a ajouté la méthode Hash#slice.

Rails 5.2.0beta1 a également ajouté sa propre version de Hash#slice afin de limiter la fonctionnalité pour les utilisateurs du framework qui utilisent une version antérieure de Ruby. https://github.com/rails/rails/commit/01ae39660243bc5f0a986e20f9c9bff312b1b5f8

Si vous cherchez à mettre en œuvre le vôtre pour une raison ou une autre, c'est également une bonne solution :

 def slice(*keys)
   keys.each_with_object(Hash.new) { |k, hash| hash[k] = self[k] if has_key?(k) }
 end unless method_defined?(:slice)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X