-1
class Foo
  attr_reader :size, :color

  def <=>
    ...


foo1 = Foo.new( size: 'large', color: 'blue'  )
foo2 = Foo.new( size: 'small'                 )
foo3 = Foo.new( color: 'green'                )
foo4 = Foo.new( size: 'small', color: 'red'   )
  ...

尺寸按小号、无号、中号、大号、超大号排序。颜色依次为绿色、无色、蓝色、红色。

如何有效地先按大小排序,然后按颜色排序?

4

3 回答 3

2

首先,我会明确声明订单:

@@size_order = {
    'small' => 1, 
    'medium' => 2, 
    'large' => 3, 
    'super-sized' => 4
}

@@color_order = {
    'green' => 1,
    'blue' => 2,
    'red' => 3
}

那么您可以按照以下方式确定<=>方法:

def <=> ( o )
    if (@size == o.size)
        if (@color == o.color) 
            return 0
        else
            return (@@color_order[@color] > @@color_order[o.color]) ? 1 : -1
        end
    else
        return (@@size_order[@size] > @@size_order[o.size]) ? 1 : -1
    end
end

这是一个测试示例

但是用两个类进行子类化可能会更好(更多的OOP) :并为每个类定义一个。FooColorSize<=>

于 2013-05-13T22:44:20.757 回答
2
class Foo
  attr_reader :size, :color
  VALID_COLORS = ["small",nil,"medium","large","super-sized"]
  VALID_SIZES  = ["green", nil, "blue", "red" ]

  def size_pos
    VALID_COLORS.index(size) || -1
  end

  def color_pos
    VALID_SIZES.index(color) || -1
  end

  def initialize(opts={})
    @size=opts[:size]
    @color=opts[:color]
  end

  def <=>(other)
    [size_pos,color_pos] <=> [other.size_pos, other.color_pos]
  end
end

foo1 = Foo.new( size: 'large', color: 'blue'  )
foo2 = Foo.new( size: 'small'                 )
foo3 = Foo.new( color: 'green'                )
foo4 = Foo.new( size: 'small', color: 'red'   )

[foo1,foo2,foo3,foo4].sort

#[#<Foo:0x000000020848d0 @size="small", @color=nil>, 
 #<Foo:0x00000002065700 @size="small", @color="red">, 
 #<Foo:0x00000002074868 @size=nil, @color="green">, 
 #<Foo:0x0000000208da98 @size="large", @color="blue"> ]

您可以通过将位置提取到类变量散列或常量中来提高性能,而不是每次都调用索引。

于 2013-05-13T22:52:20.043 回答
0

假设 'foos' 是 foo 对象的集合:

foos.sort_by {|f| [ f.size || '', f.color || '' ]}

这可能比使用排序或定义 <=> 更有效。如果要调整排序顺序,当属性为 nil 时,可以使用空字符串以外的其他内容。为了提高灵活性,您可以执行以下操作:

def sort_by_size
  foos.sort_by {|f| [ f.size || '', f.color || '' ]}
end

def sort_by_color
  foos.sort_by {|f| [ f.color|| '', f.size|| '' ]}
end
于 2013-05-13T22:57:33.230 回答