字符串/范围比较问题

这对于以下事情有意义:

irb(main):001:0> ["b", "aa", "d", "dd"].sort => ["aa", "b", "d", "dd"] 

但不适用于:

 irb(main):002:0> ("B".."AA").each{ |x| print "#{x}," } => "B".."AA" 

应该产生:B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y ,Z,AA,=>“B”……“AA”但“B”>“AA”=>真

与“B”不同。“BA”(“B”>“BA”=> false):

 irb(main):003:0> ("B".."BA").each{ |x| print "#{x}," } B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,AA,AB,AC,AD,AE,AF,AG,AH,AI,AJ,AK,AL,AM,AN,AO,AP,AQ,AR,AS,AT,AU,AV,AW,AX,AY,AZ,BA,=> "B".."BA" 

任何建议使“b”..“aa”按预期在ruby中工作?

我用

  • irb 0.9.5(05/04/13)ruby 1.8.7
  • (2009-06-12补丁级别174)[i486-linux]
  • Linux 2.6.31-19-generic#56-Ubuntu SMP Thu Jan 28 01:26:53 UTC 2010 i686 GNU / Linux

执行此操作的最佳方法是inheritanceString并重新定义比较运算符以满足您的需求。 然后使用您的新类来制作范围。

 class MyString < String def initialize str="" super str end def <=>(other) length_cmp = self.length <=> other.length return length_cmp unless length_cmp == 0 super other end end 

现在,您可以确保列显示在另一列之前。

 "b" < "aa" #=> false MyString.new("b") < MyString.new("aa") #=> true 

注意 :只有任何比较运算符左侧的字符串需要是MyString类:

 MyString.new("b") < "aa" #=> true "aa" > MyString.new("b") #=> false 

看起来Ruby正在使用succ ,但首先它检查end>=start ,因为这里是假的,所以它甚至都没有尝试。

不可否认String#succ在这里是一个奇怪的野兽:一个字符串的后继并不总是大于字符串,使用自己的比较方法。 所以我不确定这在技术上是否是一个bug。 但是,如果你不知道这个无证检查,那看起来确实很混乱 。

再说一次,从这里的其他一些答案判断,看起来它确实像你期望的某些版本的Ruby一样工作,所以它可能在1.9中修复了吗?

这是在Ruby中报告的一个错误。 结果取决于您运行的Ruby版本。 版本1.8.6和1.9.1之间存在差异。

确实,在类String中,<=>和String#succ没有完全协调


我想如果对于每一个ab最终是从a.succ.succ生成的那个 ,那将是很好的<=> b返回-1也是如此。 这样做的一个原因是它实际上是<=>succ ,它们首先用于实现范围。 因此,正如您所指出的那样, .succ最终完成扩展的Ruby String范围不起作用,因为<=>测试与它相矛盾并终止循环。

所以,是的,至少对于由<=>定义的String的排序与#succ方法排序不匹配。 这是一些开发人员避免使用succ原因之一。

任何建议使“b”..“aa”按预期在ruby中工作?

这不适用于ruby 1.8.7(2009-06-12 patchlevel 174),也不适用于ruby 1.9.1p376(2009-12-07修订版26041)[i486-linux]

“b”..“ba”确实有效……

irb(main):001:0>(“b”..“ba”)。每个{| x | 打印“#{x}”} bcdefghijklmnopqrstuv wxyz aa ab ac ad ae ag ag a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a