SGM
SGM

Reputation: 113

Ruby - Initialize has key-value in a loop

I have a hash of key value pairs, similar to -

myhash={'test1' => 'test1', 'test2 => 'test2', ...}

how can I initialize such a hash in a loop? Basically I need it to go from 1..50 with the same test$i values but I cannot figure out how to initialize it properly in a loop instead of doing it manually. I know how to loop through each key-value pair individually:

 myhash.each_pair do |key, value|

but that doesn't help with init

Upvotes: 0

Views: 730

Answers (4)

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

(1..50).map { |i| ["test#{i}"] * 2 }.to_h

The solution above is more DRY than two other answers, since "test" is not repeated twice :)

It is BTW, approx 10% faster (that would not be a case when keys and values differ):

require 'benchmark'
n = 500000
Benchmark.bm do |x| 
  x.report { n.times do   ; (1..50).map { |i| ["test#{i}"] * 2 }.to_h ; end }
  x.report { n.times do   ; (1..50).each.with_object({}) do |i, h| ; h["test#{i}"] = "test#{i}" ; end ; end }
end

     user     system      total        real
17.630000   0.000000  17.630000 ( 17.631221)
19.380000   0.000000  19.380000 ( 19.372783)

Or one might use eval:

hash = {}
(1..50).map { |i| eval "hash['test#{i}'] = 'test#{i}'" }

or even JSON#parse:

require 'json'
JSON.parse("{" << (1..50).map { |i| %Q|"test#{i}": "test#{i}"| }.join(',') << "}")

Upvotes: 4

Wand Maker
Wand Maker

Reputation: 18762

How about:

hash = (1..50).each.with_object({}) do |i, h|
    h["test#{i}"] = "test#{i}"
end

If you want to do this lazily, you could do something like below:

hash = Hash.new { |hash, key| key =~ /^test\d+/ ? hash[key] = key : nil}
p hash["test10"]
#=> "test10"
p hash
#=> {"test10"=>"test10"}

The block passed to Hash constructor will be invoked whenever a key is not found in hash, we check whether key follows a certain pattern (based on your need), and create a key-value pair in hash where value is equal to key passed.

Upvotes: 4

sawa
sawa

Reputation: 168199

You can also do this:

hash = Hash.new{|h, k| h[k] = k.itself}
(1..50).each{|i| hash["test#{i}"]}
hash # => ...

Upvotes: 1

art-solopov
art-solopov

Reputation: 4755

First of all, there's Array#to_h, which converts an array of key-value pairs into a hash.

Second, you can just initialize such a hash in a loop, just do something like this:

target = {}
1.upto(50) do |i|
  target["test_#{i}"] = "test_#{i}"
end

Upvotes: 2

Related Questions