Ruby: используйте вложенные массивы для компиляции значений с аналогичным первым элементом

#arrays #ruby

#массивы #ruby

Вопрос:

У меня есть вложенный массив Ruby, подобный этому:

 arr = [["Red", 2], ["Red", 1], ["Yellow", 0], ["Yellow", 2], ["Blue", 1]]
 

И я пытаюсь найти метод, который суммирует число (которое является вторым элементом в каждом мини-массиве) для похожих элементов, получая вложенный массив, подобный этому:

 [["Red", 3], ["Yellow", 2], ["Blue", 1]]
 

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

С не вложенным массивом вы могли бы просто использовать if и .includes? , но я не уверен, как это сделать с вложенным массивом.

Какие-нибудь мастера Ruby могут направить меня в правильном направлении?

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

1. Я отредактировал ваши массивы, чтобы сделать их допустимыми объектами Ruby, а также присвоил переменную входному массиву. Последнее позволяет читателям ссылаться на эту переменную в ответах и комментариях без необходимости ее определения. Кроме того, эти изменения облегчают вырезание и вставку в тестовый код.

Ответ №1:

Обратите внимание, что это не массив и не допустимый ruby

 ["Red", 3], ["Yellow", 2], ["Blue", 1]
 

в любом случае попробуйте это

 arr.group_by { |color, amount| color }
   .map { |k, color_arr| [k, color_arr.map(amp;:last).inject(: )] }
 => [["Red", 3], ["Yellow", 2], ["Blue", 1]]
 

или начиная с ruby 2.4.0 и выше

 arr.group_by { |color, amount| color }
   .map { |k, color_arr| [k, color_arr.map(amp;:last).sum] }
 

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

1. Спасибо! Я очень новичок в этом и действительно смог собрать его воедино! Отличное объяснение.

2. При желании, arr.group_by(amp;:first) и color_arr.sum(amp;:last)

Ответ №2:

 arr.each_with_object(Hash.new(0)) {|(col,nbr),h| h[col]  = nbr}.to_a
  #=> [["Red", 3], ["Yellow", 2], ["Blue", 1]]
 

Обратите внимание на промежуточное вычисление:

 arr.each_with_object(Hash.new(0)) {|(col,nbr),h| h[col]  = nbr}
  #=> {"Red"=>3, "Yellow"=>2, "Blue"=>1}
 

См. Hash::new .