Comment pourrais-je inverser les éléments du hachage en conservant les mêmes valeurs et clés, mais en inversant leur ordre dans le hachage?.
Ainsi:
{ "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
Et convertir cela en:
{ "1" => "spider", "lala" => "54", "10" => "cool", "4" => "happiness" }
Ou peut-être pourrais-je exécuter une boucle each
en arrière, en commençant par le dernier élément du hachage, plutôt que par le premier?
Vous pouvez convertir le hachage en tableau, l'inverser, puis le reconvertir en hachage:
reversed_h = Hash[h.to_a.reverse]
Hash#to_a
vous donne un tableau de tableaux, les tableaux internes sont de simples paires [key,value]
, puis vous inversez ce tableau en utilisant Array#reverse
et Hash[]
convertit les paires [key,value]
en un hachage.
Ruby 2.1 ajoute une méthode Array#to_h
afin que vous puissiez maintenant dire:
reversed_h = h.to_a.reverse.to_h
Dans Ruby 2.1+, vous pouvez combiner reverse_each
et to_h
:
{foo: 1, bar: 2}.reverse_each.to_h
#=> {:bar=>2, :foo=>1}
hash = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
reversed_hash = Hash[hash.to_a.reverse]
h = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
p Hash[h.reverse_each.map{|e| e}]
#=> {"1"=>"spider", "lala"=>"54", "10"=>"cool", "4"=>"happiness"}
Mais cela laisse un mauvais goût (tout comme les autres réponses, qui fonctionnent bien comme celle-ci). Si vous devez le faire, cela pourrait indiquer qu’un hachage n’est pas le meilleur choix.
reversed_h = Hash[h.to_a.collect(&:reverse)]
si besoin:
hash = {:a => :x, :b => :y, :c => :y, :d => :z}
à:
{:x => [:a], :y => [:b, c], :z => [:d] }
pouvez:
h={};hash.to_a.each{|e|h[e[1]]||=[];h[e[1]]<<e[0]};h
En Ruby pur, vous pouvez le faire par hash.map(&:reverse).to_h
ou hash.reverse_each.to_h
Dans Rails, vous pouvez le faire par hash.invert
Vous pouvez également utiliser reduce
et merge
pour ajouter l'élément à l'avant d'un nouveau hachage:
hash = { "4" => "happiness", "10" => "cool", "lala" => "54", "1" => "spider" }
hash.reduce({}){ |memo, object| Hash[*object].merge(memo) }
mais c'est fou: D
Dans Ruby 1.8.7 , il est établi que l’ordre des éléments d’un hachage n’est pas sous notre contrôle; aucune des méthodes ci-dessus ne fonctionne. Dans Ruby 1.9.3 , les choses fonctionnent et sont documentées de la même manière que les autres réponses.
$ irb1.8 h = {"4" => "bonheur", "10" => "cool", "lala" => "54", "1" => "araignée"} Hash [h.to_a (). Reverse ()] => {"Lala" => "54", "1" => "araignée", "10" => "cool", "4" => "bonheur"} quit $ irb1.9.1 h = {"4" => "bonheur", "10" => "cool", "lala" => "54", "1" => "spider"} Hash [h.to_a (). Reverse ()] => {"1" => "spider", "lala" => "54", "10 "=>" cool "," 4 "=>" bonheur "}
La façon dont Ruby 1.8.7 était si profondément enracinée pour moi que j'ai mal compris la question pendant un bon bout de temps. Je pensais que cela demandait un moyen de Hash # invert : c'est-à-dire de transformer le hachage de telle sorte que la plage mappe vers le domaine. Cette méthode élimine les doublons. Luís Ramalho propose une méthode ça ne fonctionne pas, mais c'est un peu maladroit. C'est un peu plus court:
$ irb def invertWithDuplicates (original) inverse = Hash.new () {| hash, clé | hash [clé] = []; } original.each_pair () {| clé, valeur | inverse [valeur] .Push (clé); } return inverse end h = {"4" => "bonheur", "10" => "cool", "lala" => "54", "1" => "cool"} invertWithDuplicates (h) => {"happiness" => ["4"], "cool" => ["1", "10"], "54" => ["lala"]}
Désolé de m'éloigner du sujet visé par le PO, bien que je soutienne que cela correspond au titre du message "Inverser un hachage dans Ruby".