Ruby v2.7+(最新)
从 ruby v2.7.0(2019 年 12 月发布)开始,核心语言现在包括Enumerable#tally https://ruby-doc.org/core/Enumerable.html#method-i-tally - a 新方法 https://github.com/ruby/ruby/commit/673dc51c251588be3c9f4b5b5486cd80d46dfeee,专门针对这个问题设计:
names = ["Jason", "Jason", "Teresa", "Judah", "Michelle", "Judah", "Judah", "Allison"]
names.tally
#=> {"Jason"=>2, "Teresa"=>1, "Judah"=>3, "Michelle"=>1, "Allison"=>1}
Ruby v2.4+(EOL ruby 版本,但在较新版本上仍然有效代码)
当第一次提出这个问题时(2011 年 2 月),以下代码在标准 ruby 中是不可能的,因为它使用:
-
Object#itself https://ruby-doc.org/core/Object.html#method-i-itself,已添加到 Ruby v2.2.0(2014 年 12 月发布)中。
-
Hash#transform_values http://ruby-doc.org/core/Hash.html#method-i-transform_values,已添加到 Ruby v2.4.0(2016 年 12 月发布)中。
Ruby 的这些现代附加功能支持以下实现:
names = ["Jason", "Jason", "Teresa", "Judah", "Michelle", "Judah", "Judah", "Allison"]
names.group_by(&:itself).transform_values(&:count)
#=> {"Jason"=>2, "Teresa"=>1, "Judah"=>3, "Michelle"=>1, "Allison"=>1}
Ruby v2.2+(EOL ruby 版本,但在较新版本上仍然有效代码)
对于更旧的 ruby 版本,无法访问上述内容Hash#transform_values
方法,你可以改用Array#to_h https://ruby-doc.org/core/Array.html#method-i-to_h,已添加到 Ruby v2.1.0(2013 年 12 月发布)中:
names.group_by(&:itself).map { |k,v| [k, v.length] }.to_h
#=> {"Jason"=>2, "Teresa"=>1, "Judah"=>3, "Michelle"=>1, "Allison"=>1}
For 甚至更老红宝石版本(<= 2.1
),有几种方法可以解决这个问题,但是(在我看来)没有明确的“最佳”方法。请参阅这篇文章的其他答案。