Ruby injecter avec initial étant un hash

Quelqu’un peut-il me dire pourquoi:

['a', 'b'].inject({}) {|m,e| m[e] = e } 

jette l’erreur:

 IndexError: ssortingng not matched from (irb):11:in `[]=' from (irb):11:in `block in irb_binding' from (irb):11:in `each' from (irb):11:in `inject' from (irb):11 from C:/Ruby192/bin/irb:12:in `' 

alors que le suivant fonctionne?

 a = {} a["str"] = "str" 

Votre bloc doit retourner le hash accumulé:

 ['a', 'b'].inject({}) {|m,e| m[e] = e; m } 

Au lieu de cela, il renvoie la chaîne ‘a’ après la première passe, qui devient m dans la passe suivante et vous finissez par appeler la méthode []= la chaîne.

Le bloc doit retourner l’accumulateur (le hachage), comme l’a dit @Rob. Quelques alternatives:

Avec Hash#update :

 hash = ['a', 'b'].inject({}) { |m, e| m.update(e => e) } 

Avec Enumerable#each_with_object :

 hash = ['a', 'b'].each_with_object({}) { |e, m| m[e] = e } 

Avec Hash#[] :

 hash = Hash[['a', 'b'].map { |e| [e, e] }] 

Avec Enumerable # mash de facettes:

 require 'facets' hash = ['a', 'b'].mash { |e| [e, e] } 

Avec Array#to_h (Ruby> = 2.1):

 hash = ['a', 'b'].map { |e| [e, e] }.to_h 

Plutôt que d’utiliser inject, vous devriez regarder dans Enumerable#each_with_object .

inject vous oblige à renvoyer l’object accumulé, each_with_object fait automatiquement.

De la documentation:

Itère le bloc donné pour chaque élément avec un object arbitraire donné et retourne l’object donné initialement.

Si aucun bloc n’est donné, renvoie un énumérateur.

par exemple:

 evens = (1..10).each_with_object([]) {|i, a| a << i*2 } #=> [2, 4, 6, 8, 10, 12, 14, 16, 18, 20] 

Donc, plus proche de votre question:

 [1] pry(main)> %w[ab].each_with_object({}) { |e,m| m[e] = e } => {"a"=>"a", "b"=>"b"} 

Notez que each_with_object et each_with_object inversent l’ordre des parameters each_with_object .