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 Sandmanenter sandman所以我需要它不区分大小写。 我很确定我可以通过它循环,但有一个更清洁的方式?

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

该组通过创build一个专辑名称的capitalize d版本的哈希到一个包含list中匹配它的所有string的数组(例如"Enter sandman" => ["Enter Sandman", "Enter sandman"] )。 然后map用它的长度replace每个数组,所以你得到例如["Enter sandman", 2]"Enter sandman"

如果你需要的结果是一个散列,你可以调用to_h结果或包裹一个Hash[ ]

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

另取:

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

正如我所说,你可能更喜欢titlecase

在Ruby中对未知大小的数据集进行分组和sorting应该是最后的select。 这对于DB来说是最好的一件事。 通常像你这样的问题是使用COUNTGROUP BYHAVINGORDER BY子句的组合来解决的。 幸运的是,rails为这种用例提供​​了一个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