134 votes

Quelle est la meilleure façon de convertir un tableau en hachage en Ruby ?

En Ruby, étant donné un tableau sous l'une des formes suivantes...

[apple, 1, banana, 2]
[[apple, 1], [banana, 2]]

...quelle est la meilleure façon de convertir ceci en un hash sous la forme de...

{apple => 1, banana => 2}

150voto

John Topley Points 58789

Il suffit d'utiliser Hash[*array_variable.flatten]

Par exemple :

a1 = ['apple', 1, 'banana', 2]
h1 = Hash[*a1.flatten(1)]
puts "h1: #{h1.inspect}"

a2 = [['apple', 1], ['banana', 2]]
h2 = Hash[*a2.flatten(1)]
puts "h2: #{h2.inspect}"

Utilisation Array#flatten(1) limite la récursivité de telle sorte que Array Les clés et les valeurs fonctionnent comme prévu.

4 votes

Oh, l'éloquence ! Voilà pourquoi j'aime Ruby

11 votes

AVERTISSEMENT : les réponses utilisant flatten poseront des problèmes si vous voulez des clés ou des valeurs de type tableau.

1 votes

J'ai publié ci-dessous une solution alternative qui évitera les problèmes liés aux clés ou aux valeurs des tableaux.

100voto

Stew Points 850

NOTE : Pour une solution concise et efficace, voir Réponse de Marc-André Lafortune ci-dessous.

Cette réponse a été proposée à l'origine comme une alternative aux approches utilisant flatten, qui étaient les plus votées au moment de la rédaction. J'aurais dû préciser que je n'avais pas l'intention de présenter cet exemple comme une meilleure pratique ou une approche efficace. La réponse originale suit.


Attention ! Solutions utilisant aplatir ne préservera pas les clés ou les valeurs des tableaux !

En nous appuyant sur la réponse populaire de @John Topley, essayons :

a3 = [ ['apple', 1], ['banana', 2], [['orange','seedless'], 3] ]
h3 = Hash[*a3.flatten]

Cela provoque une erreur :

ArgumentError: odd number of arguments for Hash
        from (irb):10:in `[]'
        from (irb):10

Le constructeur attendait un tableau de longueur égale (par exemple ['k1','v1,'k2','v2']). Ce qui est pire, c'est qu'un tableau différent qui s'aplatirait à une longueur paire nous donnerait silencieusement un Hash avec des valeurs incorrectes.

Si vous souhaitez utiliser des clés ou des valeurs de type tableau, vous pouvez utiliser la fonction carte :

h3 = Hash[a3.map {|key, value| [key, value]}]
puts "h3: #{h3.inspect}"

Cela permet de conserver la clé du tableau :

h3: {["orange", "seedless"]=>3, "apple"=>1, "banana"=>2}

15 votes

C'est la même chose que Hash[a3], puisque a3 == a3.map{|k,v| [k,v]} est vrai, c'est en fait l'équivalent de a3.dup.

2 votes

Au lieu d'utiliser map, pourquoi ne pas simplement spécifier la profondeur de l'aplatissement ? Par exemple : h3 = Hash[*a3.flatten(1)] au lieu de h3 = Hash[*a3.flatten] ce qui provoquerait une erreur.

3 votes

Cette réponse n'est pas efficace. Elle est également obsolète. Voir ma réponse.

91voto

La meilleure façon est d'utiliser Array#to_h :

[ [:apple,1],[:banana,2] ].to_h  #=> {apple: 1, banana: 2}

Il convient de noter que to_h accepte également un bloc :

[:apple, :banana].to_h { |fruit| [fruit, "I like #{fruit}s"] } 
  # => {apple: "I like apples", banana: "I like bananas"}

Note : to_h accepte un bloc en Ruby 2.6.0+ ; pour les premiers Ruby, vous pouvez utiliser mon fichier backports gemme et require 'backports/2.6.0/enumerable/to_h'

to_h sans bloc a été introduite dans Ruby 2.1.0.

Avant Ruby 2.1, on pouvait utiliser la formule moins lisible Hash[] :

array = [ [:apple,1],[:banana,2] ]
Hash[ array ]  #= > {:apple => 1, :banana => 2}

Enfin, il faut se méfier des solutions qui utilisent flatten Cela pourrait créer des problèmes avec les valeurs qui sont elles-mêmes des tableaux.

4 votes

Merci pour la simplicité de la nouvelle méthode .to_h !

3 votes

J'aime la to_h est meilleure que les réponses précédentes, car elle exprime l'intention de convertir les après opérant sur le tableau.

1 votes

@BSeven Neither Array#to_h ni Enumerable#to_h est dans le core ruby 1.9.

22voto

JanDintel Points 101

Mise à jour

Ruby 2.1.0 est disponible aujourd'hui . Et je viens avec Array#to_h ( notes de mise à jour et ruby-doc ), ce qui résout le problème de la conversion d'un fichier Array à un Hash .

Exemple de documentation Ruby :

[[:foo, :bar], [1, 2]].to_h    # => {:foo => :bar, 1 => 2}

8voto

Espo Points 24318

Ceci mais voici une façon de convertir un tableau en hachage :

 require "enumerator"

 class Array
   def to_h
     Hash[*enum_with_index.to_a.flatten]
   end
 end

%w{a b c d}.to_h  # =>  {"a"=>0, "b"=>1, "c"=>2, "d"=>3}

Autre exemple :

["foo", "bar", "foo1", "bar1","foo2", "bar2"]   convert to
{"foo"=>"bar", "foo1"=>"bar1","foo2"=>"bar2"}

def array_to_hash(array)
  count = 0
  hash = Hash.new
  (array.length / 2).times do
    hash[array[count]] = array[count+1]
    count += 2
  end
  return hash
end

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