我有一个对象数组,我需要通过一个可以是整数或零的位置属性进行排序,我需要将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,那么它很可能会将它们放在数组的末尾,但我不喜欢这个解决方案,因为它是任意的
答案 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