当`< =>`不是订单关系时,`sort`如何工作?

时间:2016-02-11 17:52:35

标签: ruby sorting

假设我在元素之间定义<=>关系,使它不是顺序关系(即,它不满足某些反身性,反对称性,传递性)。

class Scissors
  def <=> other
    case other
    when Scissors then 0
    when Paper then 1
    when Rock then -1
    end
  end
end

class Paper
  def <=> other
    case other
    when Scissors then -1
    when Paper then 0
    when Rock then 1
    end
  end
end

class Rock
  def <=> other
    case other
    when Scissors then 1
    when Paper then -1
    when Rock then 0
    end
  end
end

当我在这些元素中调用sort(非Schwartzian比较)时,我得到了一定的结果:

scissors = Scissors.new
paper = Paper.new
rock = Rock.new

[rock, paper, scissors].sort
# =>
# [
#   #<Rock:0x007f7a64ffaa10>,
#   #<Paper:0x007f7a64ffaa38>,
#   #<Scissors:0x007f7a64ffaa60>
# ]

[scissors, paper, rock].sort
# =>
# [
    #<Scissors:0x007f7a64ffaa60>,
    #<Rock:0x007f7a64ffaa10>,
    #<Paper:0x007f7a64ffaa38>
# ]

在这种情况下sort遵循什么逻辑?

1 个答案:

答案 0 :(得分:1)

要理解Ruby比较数组中元素的顺序,请使用下一个技巧:

[rock, paper, scissors].sort {|x,y| p [x,y]; x<=>y}
[#<Paper:0x000000080407d8>, #<Scissors:0x00000007e91c70>]
[#<Rock:0x000000080fce88>, #<Paper:0x000000080407d8>]
#=> [#<Rock:0x000000080fce88>, #<Paper:0x000000080407d8>, #<Scissors:0x00000007e91c70>]

[scissors, paper, rock].sort {|x,y| p [x,y]; x<=>y}
[#<Paper:0x000000080407d8>, #<Rock:0x000000080fce88>]
[#<Scissors:0x00000007e91c70>, #<Rock:0x000000080fce88>]
#=> [#<Scissors:0x00000007e91c70>, #<Rock:0x000000080fce88>, #<Paper:0x000000080407d8>]

如您所见,Ruby从数组的结尾开始比较。 在每次迭代中,Ruby都会比较对象,如果第二个对象小于第一个对象,它们将被交换。