Problem with Ruby Array.inject - can't see

I am trying to save values โ€‹โ€‹from an array to a hash (the value of the array is the key, the value is 0). Here is my code. Any ideas?

[1, 2, 3, 4].inject({}) {|result, e| result[e] = 0} 

This is the error I am getting.

 oMethodError: undefined method `[]=' for 0:Fixnum from (irb):1 from (irb):1:in `inject' from (irb):1:in `each' from (irb):1:in `inject' from (irb):1 from :0 
+4
source share
6 answers

The "Result" works fine, but to my taste, I prefer this method:

 [1,2,3,4].inject({}) {|result,e| result.merge!(e=>0)} 

If it is in performance-critical code, however, the taste comes at a price. Here's a quick test that performs this operation a million times.

In Ruby 1.8.5

 merge: 22s merge!: 14s ; result: 9s 

In Ruby 1.9.1

 merge: 18s merge!: 11s ; result: 5s 
+8
source

The problem is that result[e] = 0 returns the result of the operation, namely 0, and is transferred to the next iteration, where you try to call []= on it. You can get past this by doing the following:

[1, 2, 3, 4].inject({}) {|result, e| result[e] = 0; result }

+8
source

The return value of result[e] = 0 is 0, not result . You must do:

 [1, 2, 3, 4].inject({}) {|result, e| result[e] = 0; result} 

(or use merge instead of []= or use each instead of inject )

+2
source

You really have to use merge! instead of merging in this case. There is no reason to create a new hash at each iteration.

 [1,2,3,4].inject({}) {|result,e| result.merge!(e=>0)} 
0
source

It takes two lines, but you can also do

 hash = {} [1,2,3,4].each{|key| hash[key] = 0} 
0
source

If your array is a simple array in which there are no other arrays, then I would use the hash matrix dereferencing method:

 Hash[*[1,2,3,4].zip(Array.new(4,0)).flatten] 

Or perhaps a more general one:

If there are nested arrays, you only need to smooth out one level of depth, and since there is no ruby โ€‹โ€‹command for flatten_once, you just need to do it manually using concatenation. Surface - you can alternate zeros during concatenation, so you no longer need to fasten it:

 Hash[*[1,2,3,4].inject([]){|s,x| s.concat([x,0])}] 

A quick scan of 1,000,000 iterations of each on my machine in Ruby 1.8.6 gives me:

 aforementioned merge! method: 34s Hash[*...).concat([x,0])}] method: 25s aforementioned result! method: 22s Hash[*...).flatten] method: 15s 
0
source

All Articles