Подтвердить что ты не робот

Ruby: Как сгруппировать массив Ruby?

У меня есть массив Ruby

> list = Request.find_all_by_artist("Metallica").map(&:song)
=> ["Nothing else Matters", "Enter sandman", "Enter Sandman", "Master of Puppets", "Master of Puppets", "Master of Puppets"]

и мне нужен список с такими графами:

{"Nothing Else Matters" => 1,
 "Enter Sandman" => 2,
 "Master of Puppets" => 3}

В идеале я хочу, чтобы хэш дал мне счет и заметил, что у меня Enter Sandman и Enter Sandman, поэтому мне нужно, чтобы он не учитывал регистр. Я уверен, что смогу пройти через него, но есть ли более чистый способ?

4b9b3361

Ответ 1

list.group_by(&:capitalize).map {|k,v| [k, v.length]}
#=> [["Master of puppets", 3], ["Enter sandman", 2], ["Nothing else matters", 1]]

Группа создает хеш из версии capitalize d имени альбома в массив, содержащий все строки в list, которые соответствуют ему (например, "Enter sandman" => ["Enter Sandman", "Enter sandman"]). map затем заменяет каждый массив своей длиной, так что вы получаете, например. ["Enter sandman", 2] для "Enter sandman".

Если вы хотите, чтобы результат был хэшем, вы можете вызвать to_h в результате или обернуть вокруг него Hash[ ].

Ответ 2

list.inject(Hash.new(0)){|h,k| k.downcase!; h[k.capitalize] += 1;h}

Ответ 3

Другой вариант:

h = Hash.new {|hash, key| hash[key] = 0}
list.each {|song| h[song.downcase] += 1}
p h  # => {"nothing else matters"=>1, "enter sandman"=>2, "master of puppets"=>3}

Как я уже сказал, вы можете предпочесть titlecase

Ответ 4

Группировка и сортировка набора данных неизвестного размера в Ruby должны быть последним средством. Это сложнейшая задача, оставленная БД. Обычно проблемы, подобные вашей, решаются с использованием комбинаций COUNT, GROUP BY, HAVING и ORDER BY. К счастью, рельсы предоставляют метод COUNT для таких случаев использования.

song_counts= Request.count(
              :select => "LOWER(song) AS song"
              :group => :song, :order=> :song,
              :conditions => {:artist => "Metallica"})

song_counts.each do |song, count|
  p "#{song.titleize} : #{count}"
end