按字典顺序排序

5

我想要按字典顺序对我的坐标数组进行排序。但是我不确定如何实现。数组中的每个元素都是一个具有Fixnum字段#x#yCoordinate对象。

我刚接触Ruby并不一定理解排序枚举。会像这样吗?

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

您可以通过添加简短的输入和计算结果来改进您的问题。 - radubogdan
3个回答

5

首先,宇宙飞船操作符是<=>而不是<==>

其次,您没有正确组合这两个比较:比较的结果将是-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]}

这种方法更加简洁明了,但是每次比较都需要创建两个数组,会稍微消耗一些资源。

你甚至可以这样做:

 array.sort_by! { |a| [a.x, a.y] }

这个版本更加清晰,但是内存占用略有不同。它会创建一个由块返回值替换原始值的数组,并使用该数组对原始数组进行排序。

通常情况下我会使用后者,除非我有充分的理由选择另一种方式。


哦,哇,我一直在想为什么<==>会出现语法错误-_-。感谢演示。 - Jake Senior

4

Frederick Cheung的回答已经描述了如何按自定义属性排序。

另一个选项是通过实现Coordinate#<=>来提供默认的排序顺序:

class Coordinate
  # ...

  def to_a
    [x, y]
  end

  def <=>(other)
    return unless other.is_a? Coordinate

    to_a <=> other.to_a
  end
end

只需调用:

coordinate_array.sort!

您还可以包含Comparable mixin,它使用<=>来实现传统的比较运算符(<<===>=>)以及方法between?

即使您没有提到“between”,也请为对Comparable的引用点赞。 - Cary Swoveland

1

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)

请查看 数组文档了解[1, 1] <=> [1, 0]的工作原理。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接