D'accord, voici l'affaire, je cherche depuis des lustres sur Google pour trouver une solution à ce problème et bien qu'il y en ait beaucoup, ils ne semblent pas faire le travail que je recherche.
Fondamentalement, j'ai un tableau structuré comme ça
["item 1", "item 2", "item 3", "item 4"]
Je veux le convertir en hachage pour qu'il ressemble à ceci
{ "item 1" => "item 2", "item 3" => "item 4" }
c'est-à-dire que les éléments qui sont sur les index «pairs» sont les clés et les éléments sur les index «impairs» sont les valeurs.
Des idées comment faire cela proprement? Je suppose qu'une méthode de force brute consisterait simplement à extraire tous les index pairs dans un tableau séparé, puis à les contourner pour ajouter les valeurs.
*
s'appelle l' opérateur splat . Il prend un tableau et le convertit en une liste littérale d'éléments. Donc*[1,2,3,4]
=>1, 2, 3, 4
. Dans cet exemple, ce qui précède équivaut à faireHash["item 1", "item 2", "item 3", "item 4"]
. EtHash
a une[]
méthode qui accepte une liste d'arguments (en créant des clés d'index pairs et des valeurs d'index impaires), maisHash[]
n'accepte pas de tableau, nous splatons donc le tableau en utilisant*
.Hash[a.each_slice(2).to_a]
.Ruby 2.1.0 a introduit une
to_h
méthode sur Array qui fait ce dont vous avez besoin si votre tableau d'origine se compose de tableaux de paires clé-valeur: http://www.ruby-doc.org/core-2.1.0/Array.html#method -i-vers_h .la source
bar
doit être un symbole, et le symbole:2
doit être un entier. Donc, votre expression corrigée esta = [[:foo, 1], [:bar, 2]]
).Utilisez simplement
Hash.[]
avec les valeurs du tableau. Par exemple:la source
*arr
convertitarr
en une liste d'arguments, donc cela appelle la[]
méthode de Hash avec le contenu de arr comme arguments.Ou si vous avez un tableau de
[key, value]
tableaux, vous pouvez faire:la source
Hash[*arr]
{ [1, 2] => [3, 4] }
. Et puisque le titre de la question dit "Array to Hash" et que la méthode intégrée "Hash to Array" le fait:,{ 1 => 2, 3 => 4}.to_a # => [[1, 2], [3, 4]]
j'ai pensé que plus d'un pourrait s'arrêter ici en essayant d'obtenir l'inverse de la méthode intégrée "Hash to Array". En fait, c'est comme ça que j'ai fini ici de toute façon.Hash[arr]
fera le travail pour vous.#inject
méthode. Avec#merge!
,#each_with_object
aurait dû être utilisé. Si#inject
est insisté sur,#merge
plutôt que#merge!
devrait avoir été utilisé.C'est ce que je recherchais en recherchant ceci:
[{a: 1}, {b: 2}].reduce({}) { |h, v| h.merge v } => {:a=>1, :b=>2}
la source
merge
, il construit et supprime un nouveau hachage par itération de boucle et est très lent. Si vous avez un tableau de hachages, essayez à la[{a:1},{b:2}].reduce({}, :merge!)
place - il fusionne tout dans le même (nouveau) hachage..reduce(&:merge!)
[{a: 1}, {b: 2}].reduce(&:merge!)
évalue à{:a=>1, :b=>2}
[{a: 1}, {b: 2}].reduce(&:merge!)
c'est le même que[{a: 1}, {b: 2}].reduce { |m, x| m.merge(x) }
ce qui est le même que[{b: 2}].reduce({a: 1}) { |m, x| m.merge(x) }
.Enumerator
comprendEnumerable
. Depuis2.1
, aEnumerable
également une méthode#to_h
. C'est pourquoi, on peut écrire: -Parce que
#each_slice
sans bloc nous donneEnumerator
, et selon l'explication ci-dessus, nous pouvons appeler la#to_h
méthode sur l'Enumerator
objet.la source
Vous pouvez essayer comme ça, pour un seul tableau
pour tableau de tableau
la source
ou, si vous détestez
Hash[ ... ]
:ou, si vous êtes un fan paresseux de la programmation fonctionnelle cassée:
la source
Hash[ ... ]
mais que vous voulez l'utiliser comme méthode en chaîne (comme vous pouvez le faire avecto_h
), vous pouvez combiner les suggestions de Boris et écrire:arr.each_slice( 2 ).map { |e| e }.tap { |a| break Hash[a] }
Toutes les réponses supposent que le tableau de départ est unique. OP n'a pas spécifié comment gérer les tableaux avec des entrées en double, ce qui entraîne des clés en double.
Regardons:
Vous perdrez la
item 1 => item 2
paire car elle est remplacée paritem 1 => item 5
:Toutes les méthodes, y compris le
reduce(&:merge!)
résultat de la même suppression.Il se peut cependant que ce soit exactement ce à quoi vous vous attendez. Mais dans d'autres cas, vous souhaitez probablement obtenir un résultat avec une
Array
valeur pour à la place:La manière naïve serait de créer une variable d'assistance, un hachage qui a une valeur par défaut, puis de le remplir dans une boucle:
Il pourrait être possible d'utiliser
assoc
etreduce
de faire ci-dessus en une seule ligne, mais cela devient beaucoup plus difficile à raisonner et à lire.la source