Comment changer les valeurs de hachage?

Je voudrais remplacer chaque value dans un hachage par value.some_method .

Par exemple, pour un simple hash:

 {"a" => "b", "c" => "d"}` 

chaque valeur doit être .upcase d, elle ressemble à ceci:

 {"a" => "B", "c" => "D"} 

J’ai essayé #collect et #map mais je #collect toujours les tableaux. Y a-t-il une manière élégante de le faire?

METTRE À JOUR

Merde, j’ai oublié: le hachage est dans une variable d’instance qui ne devrait pas être changée. J’ai besoin d’un nouveau hachage avec les valeurs modifiées, mais je préférerais ne pas définir cette variable explicitement, puis faire une boucle sur le hachage qui la remplit. Quelque chose comme:

 new_hash = hash.magic{ ... } 

 my_hash.each { |k, v| my_hash[k] = v.upcase } 

ou, si vous préférez le faire de manière non destructive, et renvoyer un nouveau hachage au lieu de modifier my_hash :

 a_new_hash = my_hash.inject({}) { |h, (k, v)| h[k] = v.upcase; h } 

Cette dernière version présente l’avantage supplémentaire de pouvoir transformer les clés aussi.

Depuis ruby 2.4.0 vous pouvez utiliser la méthode native Hash#transform_values :

 hash = {"a" => "b", "c" => "d"} new_hash = hash.transform_values(&:upcase) # => {"a" => "B", "c" => "D"} 

Il y a aussi Hash#transform_values! destructif Hash#transform_values! version.

Vous pouvez collecter les valeurs et les convertir de Array en Hash à nouveau.

Comme ça:

 config = Hash[ config.collect {|k,v| [k, v.upcase] } ] 

Cela le fera:

 my_hash.each_with_object({}) { |(key, value), hash| hash[key] = value.upcase } 

Par opposition à l’ inject l’avantage est que vous n’avez plus besoin de renvoyer le hachage à l’intérieur du bloc.

Essayez cette fonction:

 h = {"a" => "b", "c" => "d"} h.each{|i,j| j.upcase!} # now contains {"a" => "B", "c" => "D"}. 

Il existe une méthode pour cela dans ActiveSupport v4.2.0. Il s’appelle transform_values et exécute simplement un bloc pour chaque paire clé-valeur.

Comme ils le font avec each je pense qu’il n’y a pas de meilleur moyen que de faire une boucle.

 hash = {sample: 'gach'} result = {} hash.each do |key, value| result[key] = do_stuff(value) end 

Je fais quelque chose comme ça:

new_hash = Hash [* original_hash.collect {| key, valeur | [clé, valeur + 1]}.

Cela vous fournit les facilités pour transformer la clé ou la valeur via n’importe quelle expression (et c’est non destructif, bien sûr).

Vous voudrez peut-être aller plus loin et le faire sur un hachage nested. Cela se produit certainement avec les projets Rails.

Voici un code pour vous assurer qu’un paramètre hash est en UTF-8:

  def convert_hash hash hash.inject({}) do |h,(k,v)| if v.kind_of? Ssortingng h[k] = to_utf8(v) else h[k] = convert_hash(v) end h end end # Iconv UTF-8 helper # Converts ssortingngs into valid UTF-8 # # @param [Ssortingng] untrusted_ssortingng the ssortingng to convert to UTF-8 # @return [Ssortingng] your ssortingng in UTF-8 def to_utf8 untrusted_ssortingng="" ic = Iconv.new('UTF-8//IGNORE', 'UTF-8') ic.iconv(untrusted_ssortingng + ' ')[0..-2] end 

Ruby a la méthode tap ( 1.8.7 , 1.9.3 et 2.1.0 ) qui est très utile pour des choses comme ça.

 original_hash = { :a => 'a', :b => 'b' } original_hash.clone.tap{ |h| h.each{ |k,v| h[k] = v.upcase } } # => {:a=>"A", :b=>"B"} original_hash # => {:a=>"a", :b=>"b"} 
 new_hash = old_hash.merge(old_hash) do |_key, value, _value| value.upcase end # old_hash = {"a" => "b", "c" => "d"} # new_hash = {"a" => "B", "c" => "D"} 

Spécifique aux rails

to_s quelqu’un doit appeler la méthode to_s pour chacune des valeurs et n’utilise pas Rails 4.2 (qui inclut le lien de la méthode transform_values ), vous pouvez effectuer les opérations suivantes:

 original_hash = { :a => 'a', :b => BigDecimal('23.4') } #=> {:a=>"a", :b=>#} JSON(original_hash.to_json) #=> {"a"=>"a", "b"=>"23.4"} 

Remarque: L’utilisation de la bibliothèque ‘json’ est requirejse.

Note 2: Cela transformera les clés en chaînes

Si vous savez que les valeurs sont des chaînes, vous pouvez appeler la méthode de remplacement lorsque vous êtes dans le cycle: vous modifierez ainsi la valeur.

Altohugh ceci est limité au cas où les valeurs sont des chaînes et ne répond donc pas complètement à la question, j’ai pensé que cela peut être utile à quelqu’un.