如果我有一个球列表,每个球都有颜色属性。我怎样才能干净地获得最常用颜色的球列表。
[m1,m2,m3,m4]
说,
m1.color = blue
m2.color = blue
m3.color = red
m4.color = blue
[m1,m2,m4]
是颜色最常见的球列表
我的方法是做:
[m1,m2,m3,m4].group_by{|ball| ball.color}.each do |samecolor|
my_items = samecolor.count
end
其中count定义为
class Array
def count
k =Hash.new(0)
self.each{|x|k[x]+=1}
k
end
end
my_items将是一个相同颜色组的频率哈希值。我的实施可能是错误的,我觉得必须有一个更好,更聪明的方式。 有什么想法吗?
答案 0 :(得分:5)
您找到group_by
但遗漏了max_by
max_color, max_balls = [m1,m2,m3,m4].group_by {|b| b.color}.max_by {|color, balls| balls.length}
答案 1 :(得分:2)
您的代码不错,但效率低下。如果我是你,我会寻求一个只在你的数组中迭代一次的解决方案,如下所示:
balls = [m1, m2, m3, m4]
most_idx = nil
groups = balls.inject({}) do |hsh, ball|
hsh[ball.color] = [] if hsh[ball.color].nil?
hsh[ball.color] << ball
most_idx = ball.color if hsh[most_idx].nil? || hsh[ball.color].size > hsh[most_idx].size
hsh
end
groups[most_idx] # => [m1,m2,m4]
这与group_by
基本相同,但同时它会对组进行计数并记录哪个组最大(most_idx
)。
答案 2 :(得分:2)
怎么样:
color,balls = [m1,m2,m3,m4].group_by { |b| b.color }.max_by(&:size)
答案 3 :(得分:2)
我是这样做的。基本思想使用inject将值累积为哈希值,来自“The Ruby Cookbook”中的“12 - 构建直方图”。
#!/usr/bin/env ruby class M attr_reader :color def initialize(c) @color = c end end m1 = M.new('blue') m2 = M.new('blue') m3 = M.new('red') m4 = M.new('blue') hash = [m1.color, m2.color, m3.color, m4.color].inject(Hash.new(0)){ |h, x| h[x] += 1; h } # => {"blue"=>3, "red"=>1} hash = [m1, m2, m3, m4].inject(Hash.new(0)){ |h, x| h[x.color] += 1; h } # => {"blue"=>3, "red"=>1}
有两种不同的方法,取决于您希望inject()了解对象的知识量。
答案 4 :(得分:2)
这会按频率生成反向排序的球列表
balls.group_by { |b| b.color }
.map { |k, v| [k, v.size] }
.sort_by { |k, count| -count}
答案 5 :(得分:2)
两部分,我将使用你的怪球示例,但也将包括我自己的rails示例
ary = [m1,m2,m3,m4]
colors = ary.each.map(&:color) #or ary.each.map {|t| t.color }
Hash[colors.group_by(&:w).map {|w, ws| [w, ws.length] }]
#=> {"blue" => 3, "red" => 1 }
我的ActiveRecord示例
stocks = Sp500Stock.all
Hash[stocks.group_by(&:sector).map {|w, s| [w, s.length] }].sort_by { |k,v| v }
#=> {"Health Care" => 36, etc]
答案 6 :(得分:0)
myhash = {}
mylist.each do |ball|
if myhash[ball.color]
myhash[ball.color] += 1
else
myhash[ball.color] = 1
end
end
puts myhash.sort{|a,b| b[1] <=> a[1]}