0

I have the following array

ages = [["a", 15],["b", 16], ["c", 15], ["d", 16], ["e", 17], ["f", 20]]

I have to create a hash with ages as values such that it looks like this

{15 => ["a","c"], 16=> ["b","d]....}

when I run the group_by method:

puts ages.group_by {|list| list[1]}

this is what i get:

{15=>[["a", 15], ["c", 15]], 16=>[["b", 16], ["d", 16]], 17=>[["e", 17]], 20=>[["f", 20]]}

I'd really appreciate it if you can clarify how to make this cleaner and get the values as an array of names with same ages.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
user13350731
  • 37
  • 1
  • 2

2 Answers2

2
ages = [["a", 15],["b", 16], ["c", 15], ["d", 16], ["e", 17], ["f", 20]]

You can simplify your first step:

ages.group_by(&:last)
  #=> {15=>[["a", 15], ["c", 15]],
  #    16=>[["b", 16], ["d", 16]],
  #    17=>[["e", 17]],
  #    20=>[["f", 20]]}

You then need only transform the values to the desired arrays:

ages.group_by(&:last).transform_values { |arr| arr.map(&:first) }
  #=> {15=>["a", "c"],
  #    16=>["b", "d"],
  #    17=>["e"],
  #    20=>["f"]}

When

arr = [["a", 15], ["c", 15]]

for example,

arr.map(&:first)
  #=> ["a", "c"] 

See Hash#transform_values.

Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
0

The first thing that comes to mind is

irb(main):012:0> ages.group_by {|e| e[1]}.map {|k, v| [k, v.map(&:first)]}.to_h
=> {15=>["a", "c"], 16=>["b", "d"], 17=>["e"], 20=>["f"]}

Here we map the hash to key-value pairs, map the values of each pair to first elements then convert the pairs back to a hash.

ggorlen
  • 44,755
  • 7
  • 76
  • 106
  • This is really helpful! Thank you. Like you said, there must be a shorter way but from where i am standing, this is great too. – user13350731 Oct 26 '20 at 00:58
  • Yeah knowing Ruby there's a better way, but at least this gets you started. We'll see what shows up in the thread later on. – ggorlen Oct 26 '20 at 01:08