按字典顺序排序

时间:2015-02-17 08:12:54

标签: ruby sorting

所以我想按字典顺序对坐标数组进行排序。但我不知道该怎么做。数组中的每个元素都是Coordinate个对象,Fixnum个字段#x#y

我是Ruby的新手,并不一定了解排序​​枚举。 它会是这样的吗?

coordinate_array.sort! { |a,b| a.x <==> b.x && a.y <==> b.y }

3 个答案:

答案 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]的工作原理。