我有一组2个或更多我想订购的物品。我一直这样做:
card.max_by{|strength| strength.score
分数是一个整数分数,我根据一些任意规则计算出来。我知道这将是我要重构的东西,所以现在我正在这样做。给手分数的“干净”方法是给它一系列值,比如
foo.score = [9,3,nil,4]
将它与另一只可能有像
这样的数组的手相比较bar.score = [5,10,12,12]
和foo< => bar会告诉我foo是更大的数组,所以它应该由max_by返回。问题是max_by显然不会对数组进行比较。有没有其他方法可以按数组值排序?
答案 0 :(得分:2)
max_by
可以正常使用数组“属性”:
# Phrogz's example Hand = Struct.new(:score) hands = [ Hand.new([9,3,0,4]), Hand.new([8,8,8,8]), Hand.new([5,10,12,12]), Hand.new([1,99,99,99]) ] # hands.max_by(&:score) # => #<struct Hand score=[9, 3, 0, 4]>
但是,如果数组可以包含不相互比较的nils或其他值,<=>
可能会返回nil而max_by
可能会失败。
答案 1 :(得分:1)
如果它只是您想要的基于数组的排序(您确实需要太空船运营商)并且您希望通过排序找到“最大”,那么:
Hand = Struct.new(:score)
hands = [
Hand.new([9,3,0,4]),
Hand.new([8,8,8,8]),
Hand.new([5,10,12,12]),
Hand.new([1,99,99,99])
]
biggest = hands.sort_by(&:score).last
p biggest
#=> #<struct Hand score=[9, 3, 0, 4]>
但是,如果你真的只需要找到最大的手,那么以下将比订购整个阵列更有效:
biggest = hands.inject do |max,hand|
if (max.score <=> hand.score) == -1
hand
else
max
end
end
p biggest
#=> #<struct Hand score=[9, 3, 0, 4]>
编辑:阅读您的评论,如果您确实需要多个匹配的值,我会这样做:
Hand = Struct.new(:name,:score) do
MAX_SCORE_PART = 13 # 13 ranks in a suit
def numeric_score
value = 0
score.each_with_index do |part,i|
value += part.to_i * MAX_SCORE_PART**(score.length-i-1)
end
value
end
end
hands = [
Hand.new('Bob', [9,3,nil,4] ),
Hand.new('Jim', [8,8,8,8] ),
Hand.new('Foo', [5,10,12,12]),
Hand.new('Sam', [1,13,13,13]),
Hand.new('Zak', [9,3,0,4] ),
]
require 'pp'
by_score = hands.group_by(&:numeric_score)
pp by_score
#=> {20284=>
#=> [#<struct Hand name="Bob", score=[9, 3, nil, 4]>,
#=> #<struct Hand name="Zak", score=[9, 3, 0, 4]>],
#=> 19040=>[#<struct Hand name="Jim", score=[8, 8, 8, 8]>],
#=> 12843=>[#<struct Hand name="Foo", score=[5, 10, 12, 12]>],
#=> 4576=>[#<struct Hand name="Sam", score=[1, 13, 13, 13]>]}
pp by_score[by_score.keys.max]
#=> [#<struct Hand name="Bob", score=[9, 3, nil, 4]>,
#=> #<struct Hand name="Zak", score=[9, 3, 0, 4]>]
对于基于inject
的实施:
def numeric_score
score.enum_for(:inject,0).with_index do |(val,part),i|
val += part.to_i * MAX_SCORE_PART**(score.length-i-1)
end
end