Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set multiple keys to the same value at once for a Ruby hash

Tags:

ruby

hash

I'm trying to create this huge hash, where there are many keys but only a few values.

So far I have it like so...

du_factor = {
  "A" => 1,
  "B" => 1,
  "C" => 1,
  "D" => 2,
  "E" => 2,
  "F" => 2,

...etc., etc., etc., on and on and on for longer than you even want to know. What's a shorter and more elegant way of creating this hash without flipping its structure entirely?

Edit: Hey so, I realized there was a waaaay easier and more elegant way to do this than the answers given. Just declare an empty hash, then declare some arrays with the keys you want, then use a for statement to insert them into the array, like so:

du1 = ["A", "B", "C"]
du2 = ["D", "E", "F"]

dufactor = {}

for i in du1
  dufactor[i] = 1
end

for i in du740
  dufactor[i] = 2
end

...but the fact that nobody suggested that makes me, the extreme Ruby n00b, think that there must be a reason why I shouldn't do it this way. Performance issues?

like image 250
Stephen Smith Avatar asked Oct 31 '15 07:10

Stephen Smith


People also ask

Can a Hash have multiple values Ruby?

Prerequisites: Hashes and Arrays in Ruby Arrays and hashes are data structures that allow you to store multiple values at once.

Can a Key have multiple values Ruby?

Can a key have multiple values Ruby? Multiple Values For One Key Words are unique, but they can have multiple values (definitions) associated with them.

Can Hash have multiple values?

You can only store scalar values in a hash. References, however, are scalars. This solves the problem of storing multiple values for one key by making $hash{$key} a reference to an array containing values for $key .

How do you create a key value pair in Ruby?

Using {} braces: In this hash variable is followed by = and curly braces {}. Between curly braces {}, the key/value pairs are created.


2 Answers

Combining Ranges with a case block might be another option (depending on the problem you are trying to solve):

case foo
when ('A'..'C') then 1
when ('D'..'E') then 2
# ...
end

Especially if you focus on your source code's readability.

like image 143
spickermann Avatar answered Nov 15 '22 04:11

spickermann


How about:

vals_to_keys = {
  1 => [*'A'..'C'],
  2 => [*'D'..'F'],
  3 => [*'G'..'L'],
  4 => ['dog', 'cat', 'pig'],
  5 => [1,2,3,4]
}

vals_to_keys.each_with_object({}) { |(v,arr),h| arr.each { |k| h[k] = v } }
  #=> {"A"=>1, "B"=>1, "C"=>1, "D"=>2, "E"=>2, "F"=>2, "G"=>3, "H"=>3, "I"=>3,  
  #    "J"=>3, "K"=>3, "L"=>3, "dog"=>4, "cat"=>4, "pig"=>4, 1=>5, 2=>5, 3=>5, 4=>5}
like image 39
Cary Swoveland Avatar answered Nov 15 '22 04:11

Cary Swoveland