2013-03-14 61 views
10

我想通过评估两个属性来指定一个自定义块方法来对ruby中的对象数组进行排序。然而,在谷歌搜索后,我没有得到任何示例没有< =>运算符。ruby​​中的自定义排序方法

这就是我想做的事: 比较A对B:

if a.x less than b.x return -1 
if a.x greater than b.x return 1 
if a.x equals b.x, then compare by another property , like a.y vs b.y 

这是我的代码(小白在红宝石,对不起),它不工作...

ar.sort! do |a,b| 
    if a.x < b.y return -1 
    elseif a.x > b.x return 1 
    else return a.y <=> b.y 
end 

这个块在一个函数内,所以返回函数返回并返回-1 ...我会很感激这方面的帮助。

亲切的问候。

+0

为什么不使用排序方法? – 2013-03-14 04:19:23

+0

@Gashner我正在使用它,但我打算定制评估。 – alexserver 2013-03-14 05:32:36

+0

为什么排除'<=>'?因为你想要这么做吗? – 2013-03-14 07:35:24

回答

13

随着case语句:

ar.sort do |a, b| 
    case 
    when a.x < b.x 
    -1 
    when a.x > b.x 
    1 
    else 
    a.y <=> b.y 
    end 
end 

三元:

ar.sort { |a,b| a.x < b.x ? -1 : (a.x > b.x ? 1 : (a.y <=> b.y)) } 
+0

谢谢,这工作! – alexserver 2013-03-14 05:33:20

+5

出于可读性/维护的原因,不鼓励使用红宝石中的多级三元语句。 – 2013-03-14 07:30:36

23

这会给你的X升序则Y:

points.sort_by{ |p| [p.x, p.y] } 
+0

对于'sort_by'和'Array#<=>'具有完全符合OP要求的语义。 – dbenhur 2013-03-14 07:04:37

+0

这是_very_优雅!干得好 - 应该是被接受的答案,恕我直言 – Sebastian 2014-11-24 17:14:11

0

这似乎工作:

# Ascending 
ar.sort! do |a,b| 
    (a-b).abs() > 0 ? a-b : 0 
end 

# Descending 
ar.sort! do |a,b| 
    (a-b).abs() > 0 ? b-a : 0 
end 

太空船运营商没有必要(<=>) - 在Ruby中(在语法效率方面)似乎是多余的,因为Ruby认为0是真实的,对于这个用法(上面),您可以放在三元运算符中明确的0