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

Chr*_*ier 37 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
Run Code Online (Sandbox Code Playgroud)

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

gle*_*nra 104

我只想调整你的排序,把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]
Run Code Online (Sandbox Code Playgroud)

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

  • 同意,这应该是公认的答案.如果你乐于依赖真实和虚假的价值观,你可以缩短一点:`foo.sort {| a,b | a <=> b || (b && 1)|| -1}` (3认同)
  • 谢谢!这应该是公认的答案. (2认同)

gle*_*ald 16

我处理这样的事情:

 children.sort_by {|child| [child.position ? 0 : 1,child.position || 0]}
Run Code Online (Sandbox Code Playgroud)

  • 是的,我用两元素子阵列表示每个孩子:[0,position]如果位置不是nil,[1,0]如果位置是nil.Ruby的数组比较按顺序比较键,因此所有以0开头的子数组(非零位置)先排序,然后按位置排序.然后所有的子阵列都有1(零位).从技术上讲,这些nils然后由那些"0"代替,这就是为什么0可以是42或"馅饼"或其他什么.如果你有另一个标准可以用来改变nils,那就转而去了.不能只留下零,因为它没有<=>方法. (2认同)

Bri*_*ell 15

如何在Child定义<=>基于category.positionif 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
Run Code Online (Sandbox Code Playgroud)

然后在Parent你可以打电话children.sort.

  • 我对此有些不确定,因为它限制了你对其他任何东西进行排序的能力,而不会产生不一致.话虽如此,如果position是父母的自然排序顺序,那么以这种方式做到这一点是合理的. (3认同)

RHS*_*ger 6

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

你不能在比较中检查nil:

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

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