所以我想按字典顺序对坐标数组进行排序。但我不知道该怎么做。数组中的每个元素都是Coordinate
个对象,Fixnum
个字段#x
和#y
。
我是Ruby的新手,并不一定了解排序枚举。 它会是这样的吗?
coordinate_array.sort! { |a,b| a.x <==> b.x && a.y <==> b.y }
答案 0 :(得分:4)
首先,宇宙飞船运营商为<=>
而不是<==>
其次,你没有正确地组合2个比较:比较的结果将是-1,0或1.这些都是真值,而true && foo
只是foo
,所以你的代码只会按y值排序
您可以将其写为
x_ordering = a.x <=> b.x
x_ordering == 0 ? a.y <=> b.y : x_ordering
但是数组已经实现了<=>
所以你可以做到
array.sort! { |a,b| [a.x, a.y] <=> [b.x, b.y]}
在每次比较中创建2个数组时,这是一个更小的更清晰,更清晰
你甚至可以做到
array.sort_by! { |a| [a.x, a.y] }
哪个更清晰,但内存配置略有不同。这将创建一个数组,其原始值将替换为块返回的值,并使用它来对原始数组进行排序。
我通常会使用后一种版本,除非我有其他令人信服的理由。
答案 1 :(得分:3)
Frederick Cheung's answer已经描述了如何按自定义属性进行排序。
另一个选择是通过实施Coordinate#<=>
提供默认排序顺序:
class Coordinate
# ...
def to_a
[x, y]
end
def <=>(other)
to_a <=> other.to_a
end
end
然后致电:
coordinate_array.sort!
您还可以添加Comparable
mixin ......
(...)使用
<=>
来实现传统的比较运算符(<
,<=
,==
,>=
和{{1} })和方法>
。
答案 2 :(得分:0)
Stefan已经描述了如何为您的班级实施<=>()
方法。这是另一种方式:
class Coordinate
attr_reader :x, :y
def to_s
"(#{x}, #{y})"
end
def initialize(x, y)
@x = x
@y = y
end
def <=>(other)
[x, y] <=> [other.x, other.y]
end
end
arr = [
Coordinate.new(1, 2),
Coordinate.new(0, 3),
Coordinate.new(0, 2),
]
puts arr
puts "-" * 10
puts arr.sort!
--output:--
(1, 2)
(0, 3)
(0, 2)
----------
(0, 2)
(0, 3)
(1, 2)
请参阅Array docs了解[1, 1] <=> [1, 0]
的工作原理。