<=>
方法应分别为“小于”,“等于”和“大于”返回-1
,0
或1
。对于某些类型的可排序对象,将排序顺序基于多个属性是正常的。以下是有效的,但我觉得它看起来很笨拙:
class LeagueStats
attr_accessor :points, :goal_diff
def initialize pts, gd
@points = pts
@goal_diff = gd
end
def <=> other
compare_pts = points <=> other.points
return compare_pts unless compare_pts == 0
goal_diff <=> other.goal_diff
end
end
试一试:
[
LeagueStats.new( 10, 7 ),
LeagueStats.new( 10, 5 ),
LeagueStats.new( 9, 6 )
].sort
# => [
# #<LS @points=9, @goal_diff=6>,
# #<LS @points=10, @goal_diff=5>,
# #<LS @points=10, @goal_diff=7>
# ]
Perl将0
视为假值,允许使用不同语法进行复杂比较:
{
return ( $self->points <=> $other->points ) ||
( $self->goal_diff <=> $other->goal_diff );
}
我通过0
运算符在||
上找到了简单易读和优雅。我喜欢使用||
的一件事是,一旦比较有价值,计算就会短路。
我在Ruby中找不到类似的东西。有没有更好的方法来构建相同的比较复合体(或任何其他选择第一个非零项目的东西),理想情况下无需提前计算所有值?
答案 0 :(得分:7)
除了sawa的回答之外,结果也可以进行就地评估,以便返回-1,0或+1:
class LeagueStats
def <=> other
[points, goal_diff] <=> [other.points, other.goal_diff]
end
end
这是因为Array#<=>
:
阵列以“元素方式”进行比较;前两个 不相等的元素将决定的返回值 整个比较。
实施<=>
后,您可以加入Comparable
并获取<
,<=
,==
,>=
,>
和between?
免费。
答案 1 :(得分:3)
您可以使用Enumerable#sort_by
代替sort
:
[LeagueStats.new(10,7),LeagueStats.new(10,5),LeagueStats.new(9,6)].sort_by { |ls|
[ls.points, ls.goal_diff]
}
# => [#<LeagueStats:0x00000001a806c8 @points=9, @goal_diff=6>,
# #<LeagueStats:0x00000001a806f0 @points=10, @goal_diff=5>,
# #<LeagueStats:0x00000001a80718 @points=10, @goal_diff=7>]
class LeagueStats
...
def to_a
[points, goal_diff]
end
def <=> other
to_a <=> other.to_a
end
end