通过可能为nil的属性对ruby数组对象进行排序

时间:2009-04-30 18:12:51

标签: ruby arrays sorting

我有一个对象数组,我需要通过一个可以是整数或零的位置属性进行排序,我需要将nil位置的对象放在数组的末尾。现在,我可以强制该位置返回一些值而不是nil,以便array.sort不会失败,但如果我使用0作为默认值,那么它将这些对象放在排序的前面。这种方法最好的方法是什么?我应该将nil值设置为一些“几乎”始终保证最终的可笑高数字吗?或者是否有其他方法可以使array.sort方法将nil属性对象放在数组的末尾?代码如下所示:

class Parent
  def sorted_children
     children.sort{|a, b| a.position <=> b.position}
  end
end

class Child
  def position
    category ? category.position : #what should the else be??
  end
end

现在,如果我将'else'设为1000000000,那么它很可能会将它们放在数组的末尾,但我不喜欢这个解决方案,因为它是任意的

7 个答案:

答案 0 :(得分:97)

我只想调整你的排序,将nil项目放在最后。尝试这样的事情。

foo = [nil, -3, 100, 4, 6, nil, 4, nil, 23]

foo.sort { |a,b| a && b ? a <=> b : a ? -1 : 1 }

=> [-3, 4, 4, 6, 23, 100, nil, nil, nil]

这就是说:如果a和b都是非零的,那么它们通常会排序,但是如果其中一个是nil,则返回一个更大的状态。

答案 1 :(得分:16)

我处理这样的事情:

 children.sort_by {|child| [child.position ? 0 : 1,child.position || 0]}

答案 2 :(得分:15)

Child <=>如果category.position存在,category如果category存在,那么如果category排序的项目总是大于class Child # Not strictly necessary, but will define other comparisons based on <=> include Comparable def <=> other return 0 if !category && !other.category return 1 if !category return -1 if !other.category category.position <=> other.category.position end end 一个Parent

children.sort

然后在{{1}}中,您只需拨打{{1}}。

答案 3 :(得分:6)

公平地说,我对Ruby并不是很熟悉,所以把它作为一个算法想法而不是一个代码...并重写?:运算符,因为Ruby有更清洁的东西。

你不能在比较中检查nil:

class Parent
  def sorted_children
     children.sort{|a,b|( a and b ) ? a <=> b : ( a ? -1 : 1 ) }
  end
end

编辑使用Glenra的代码,该代码实现了与我相同的功能,但代码量更小(也可能更容易阅读)。

答案 4 :(得分:1)

我有一段时间没做过Ruby,但你可以从排序中拆分空值检查(只允许Child#位置返回null):

def sorted_children
  children.reject{|c| c.position.nil?}.sort_by(&:position) +
    children.select{|c| c.position.nil?}
end

不可否认,这不是最有效的解决方案,但它没有任何神奇的数字。

答案 5 :(得分:1)

您可以通过定义新的比较方法来覆盖飞船运营商。

class Child
  include Comparable   
  def compare_by_category(other)
    return 0 if !category && !other.category
    return 1 if !category
    return -1 if !other.category
    category.position <=> other.category.position
  end
end

sort方法可以占用一个块,因此您可以使用这种新方法进行排序:

children.sort {|a,b| a.compare_by_category(b) }

答案 6 :(得分:0)

对我来说最简单的解决方案是

def sorted_children(children)
  children.sort_by { |child| child.position || -1}
end