3

I'm trying to build a hash with:

hash = {}

strings = ["one", "two", "three"]

array = [1, 2, 3, 4, 5, 6]

so that I end up with:

hash = { "one" => [1, 2] ,
         "two" => [3, 4] ,
         "three" => [5, 6] }

I have tried:

strings.each do |string|
  array.each_slice(2) do |numbers|
    hash[string] = [numbers[0], numbers[1]]
  end
end

But that yields:

hash = { "one" => [5,6] , "two" => [5,6], "three" => [5,6] }

I know why it does this (nested loops) but I don't know how to achieve what I'm looking for.

steve_gallagher
  • 3,778
  • 8
  • 33
  • 51

3 Answers3

14

If you want a one-liner:

hash = Hash[strings.zip(array.each_slice(2))]

For example:

>> strings = ["one", "two", "three"]
>> array = [1, 2, 3, 4, 5, 6]
>> hash = Hash[strings.zip(array.each_slice(2))]
=> {"one"=>[1, 2], "two"=>[3, 4], "three"=>[5, 6]}
mu is too short
  • 426,620
  • 70
  • 833
  • 800
1
hash = {}
strings.each { |string| hash[string] = array.slice!(0..1) }

This is a solution using methods and techniques you seem familiar with. It is not a 'one liner' solution but if you are new might be more understandable for you. The first answer is very elegant though.

mu is too short
  • 426,620
  • 70
  • 833
  • 800
slindsey3000
  • 4,053
  • 5
  • 36
  • 56
0

As Mu says, Zip method is the best choose:

Converts any arguments to arrays, then merges elements of self with corresponding elements from each argument. This generates a sequence of self.size n-element arrays, where n is one more that the count of arguments. If the size of any argument is less than enumObj.size, nil values are supplied. If a block is given, it is invoked for each output array, otherwise an array of arrays is returned.

sparkle
  • 7,530
  • 22
  • 69
  • 131