Ahmad hamza
Ahmad hamza

Reputation: 1936

Convert array of arrays to hash with first array's element as a key to the hash

I want to convert this array

[['a', 'b'],['c', 'd'],['e', 'f']] 

to this hash

{
  "a" : "c",
  "b" : "d"
},
{
  "a" : "e",
  "b" : "f"
}

How to do it?

I tried to use group_by and normal iterators but no luck so far. Any ideas?

Upvotes: 2

Views: 2329

Answers (5)

hirolau
hirolau

Reputation: 13901

I would write:

key = a.shift
p a.map{|x| key.zip(x).to_h } => [{"a"=>"c", "b"=>"d"}, {"a"=>"e", "b"=>"f"}]

Upvotes: 1

Cary Swoveland
Cary Swoveland

Reputation: 110675

I would use Array#product:

arr = [[:a, :b], [:c, :d], [:e, :f]]

arr.first.product(arr[1..-1]).map(&:to_h)
  #=> [{:a=>:c, :b=>:d}, {:a=>:e, :b=>:f}]

If arr can be modified, we can write:

arr.shift.product(arr).map(&:to_h)

Upvotes: 2

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121000

▶ arr = [[:a, :b],[:c, :d],[:e, :f],[:g, :h]]
▶ key, values = arr.first, arr[1..-1]
▶ values.map { |v| key.zip v }.map &:to_h
#⇒ [
#  [0] {
#    :a => :c,
#    :b => :d
#  },
#  [1] {
#    :a => :e,
#    :b => :f
#  },
#  [2] {
#    :a => :g,
#    :b => :h
#  }
# ]

Please note that unlike other solutions presented here at the moment this one will map first element as keys to a tail of arbitrary length.

UPD For legacy rubies, not having Array#to_h:

values.map { |v| key.zip v }.map { |e| Hash[e] }

Upvotes: 7

pangpang
pangpang

Reputation: 8821

a= [['a', 'b'],['c', 'd'],['e', 'f']]

a[1..-1].inject([]) { |sum, s| sum << {a[0][0] => s[0], a[0][1] => s[1]} }

=> [{"a"=>"c", "b"=>"d"}, {"a"=>"e", "b"=>"f"}]

improved:

a= [['a', 'b', 'c'],['d', 'e', 'f'],['g', 'h', 'k']]
a[1..-1].inject([]) do |sum, s|
    hash = {}
    a[0].each_with_index { |it, i| hash.merge!({it => s[i]}) }
    sum << hash
end
=> [{"a"=>"d", "b"=>"e", "c"=>"f"}, {"a"=>"g", "b"=>"h", "c"=>"k"}]

This way is more flexible.

Upvotes: 1

iced
iced

Reputation: 1572

x = [["a", "b"],["c", "d"],["e", "f"]]
x[1..-1].map { |vs| {x[0][0] => vs[0], x[0][1] => vs[1]} }

Something like this.

Upvotes: 1

Related Questions