字符串/范围比较问题

时间:2010-02-15 17:44:22

标签: ruby language-design

这对于以下内容有意义:

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 patchlevel 174)[i486-linux]
  • Linux 2.6.31-19-generic#56-Ubuntu SMP Thu Jan 28 01:26:53 UTC 2010 i686 GNU / Linux

5 个答案:

答案 0 :(得分:1)

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

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

N.B。:只有任何比较运算符左侧的字符串需要属于MyString类:

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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

  

任何建议使“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(主):001:0&GT; (“b”..“ba”)。每个{| x |打印“#{x}”} b c d e f g h i j k l m n o p q r s t u v w y y a a ac 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 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 “B” .. “BA”

答案 3 :(得分:0)

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

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

然后再说一遍,从这里的其他一些答案判断,看起来它在某些版本的Ruby中可以正常工作,所以它可能在1.9中被修复了吗?

答案 4 :(得分:0)

确实在类String中,&lt; =&gt;和字符串#succ不完全一致


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

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