Ruby:如何对 Ruby 数组进行分组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3884829/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ruby: How to group a Ruby array?
提问by Matt Elhotiby
I have a Ruby array
我有一个 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"]
and I want a list with the counts like this:
我想要一个像这样计数的列表:
{"Nothing Else Matters" => 1,
"Enter Sandman" => 2,
"Master of Puppets" => 3}
So ideally I want a hash that will give me the count and notice how I have Enter Sandmanand enter sandmanso I need it case insensitive. I am pretty sure I can loop through it but is there a cleaner way?
所以理想情况下,我想要一个散列,它会给我计数并注意我的情况Enter Sandman,enter sandman所以我需要它不区分大小写。我很确定我可以循环遍历它,但是有更干净的方法吗?
回答by sepp2k
list.group_by(&:capitalize).map {|k,v| [k, v.length]}
#=> [["Master of puppets", 3], ["Enter sandman", 2], ["Nothing else matters", 1]]
The group by creates a hash from the capitalized version of an album name to an array containing all the strings in listthat match it (e.g. "Enter sandman" => ["Enter Sandman", "Enter sandman"]). The mapthen replaces each array with its length, so you get e.g. ["Enter sandman", 2]for "Enter sandman".
group by 创建从capitalize专辑名称的d 版本到包含list匹配它的所有字符串的数组的散列(例如"Enter sandman" => ["Enter Sandman", "Enter sandman"])。在map随后替换其长度每个数组,这样就可以获得如["Enter sandman", 2]对"Enter sandman"。
If you need the result to be a hash, you can call to_hon the result or wrap a Hash[ ]around it.
如果你需要结果是一个散列,你可以调用to_h结果或者用 a 包裹Hash[ ]它。
回答by ghostdog74
list.inject(Hash.new(0)){|h,k| k.downcase!; h[k.capitalize] += 1;h}
回答by glenn Hymanman
回答by Harish Shetty
Grouping and sorting of a data set of unknown size in Ruby should be a choice of last resort. This is a chore best left to DB. Typically problems like yours is solved using a combination of COUNT, GROUP BY, HAVINGand ORDER BYclauses. Fortunately, rails provides a countmethod for such use cases.
在 Ruby 中对未知大小的数据集进行分组和排序应该是最后的选择。这是最好留给 DB 的苦差事。通常,像你这样的问题是使用的组合解决了COUNT,GROUP BY,HAVING和ORDER BY条款。幸运的是,railscount为此类用例提供了一种方法。
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
回答by ray
Late but clean answer I have,
我有迟到但干净的答案,
l = list.group_by(&:titleize)
l.merge(l) { |k,v| l[k] = v.count }
Note: If we do want unique keys i.e. without titleize, then replace it with itself
注意:如果我们确实想要唯一键,即没有titleize,则将其替换为itself
回答by BrunoFacca
As of Ruby 2.7, you can use Enumerable#tally.
从 Ruby 2.7 开始,您可以使用Enumerable#tally.
list.tally
# => {"Nothing else Matters"=>1, "Enter sandman"=>1, "Enter Sandman"=>1, "Master of Puppets"=>3}

