6

我有一个Arrayof Arrays,我想按最长到最短排序。我很容易做到这一点sort_by

> a =  [ [1, 2, 9],
         [4, 5, 6, 7],
         [1, 2, 3] ]
> a.sort_by(&:length).reverse # or a.sort_by {|e| e.length}.reverse
=> [[4, 5, 6, 7], [1, 2, 3], [1, 2, 9]]

然而,我想要的是对等长的列表有一种平局。如果两个列表的长度相等,则最后一个条目较大的列表应该排在第一位。所以在上面,[1, 2, 9]应该[1, 2, 3]切换。

我不在乎两个列表的长度相等且最后一个元素相等的情况,如果发生这种情况,它们可以按任何顺序排列。我不知道是否/如何通过 ruby​​ 内置排序来实现这一点。

4

3 回答 3

14

您仍然可以这样做sort_by,您只需要意识到Ruby 数组逐个元素进行比较

ary <=> other_ary → -1、0、+1 或 nil

[...]

比较每个数组中的每个对象(使用 <=> 运算符)。

数组以“元素方式”的方式进行比较;不相等的前两个元素将确定整个比较的返回值。

这意味着您可以使用数组作为sort_by键,然后输入一些整数否定来反转排序顺序,您会得到:

a.sort_by { |e| [-e.length, -e.last] }

这会给你[[4, 5, 6, 7], [1, 2, 9], [1, 2, 3]]你正在寻找的。

如果您不使用数字,因此“否定颠倒顺序”的技巧将不起作用,那么请使用Shaunak 的sort方法。

于 2013-08-16T02:26:14.163 回答
3

There you go :

a =  [ [1, 2, 9],[4, 5, 6, 7],[1, 2, 3] ]
a.sort { |a, b| (b.count <=> a.count) == 0 ? (b.last <=> a.last): (b.count <=> a.count)  } 

That should give you:

[[4, 5, 6, 7], [1, 2, 9], [1, 2, 3]]

How this works: we pass a block to sort function, which first checks if the array length is same, if not it continues to check for last element.

于 2013-08-16T02:13:46.580 回答
2

你可以使用

a.sort_by {|i| [i.length, i.last] }.reverse
# => [[4, 5, 6, 7], [1, 2, 9], [1, 2, 3]]
于 2013-08-16T06:21:46.263 回答