Создайте хэш из массива с помощью group_by

#ruby #group-by #ruby-hash

#ruby #группировка по #ruby-хэш

Вопрос:

У меня есть следующий массив

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

Я должен создать хэш с возрастом в качестве значений, чтобы он выглядел так

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

когда я запускаю метод group_by:

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

это то, что я получаю:

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

Я был бы очень признателен, если бы вы могли уточнить, как сделать это более чистым и получить значения в виде массива имен с одинаковым возрастом.

Ответ №1:

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

Вы можете упростить свой первый шаг:

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

Затем вам нужно только преобразовать значения в нужные массивы:

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

Когда

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

например,

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

См. раздел Hash#transform_values .

Ответ №2:

Первое, что приходит на ум, это

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

Здесь мы сопоставляем хэш с парами ключ-значение, сопоставляем значения каждой пары с первыми элементами, а затем преобразуем пары обратно в хэш.

Комментарии:

1. Это действительно полезно! Спасибо. Как вы сказали, должен быть более короткий путь, но с моей точки зрения это тоже здорово.

2. Да, зная Ruby, есть лучший способ, но, по крайней мере, это поможет вам начать. Мы посмотрим, что появится в потоке позже.