2012-01-17 188 views
20

我有一个mulitdimensional阵列像这样:排序:排序阵列基于多个条件红宝石

[ 
    [name, age, date, gender] 
    [name, age, date, gender] 
    [..] 
] 

我想知道,根据多个条件这个数组排序的最好方法......例如,如何我会根据年龄第一个然后按名称?

我插科打诨与sort方法,像这样:

array.sort { |a,b| [ a[1], a[0] ] <=> [ b[1], b[0] ] } 

除此之外我真的不明白这个语法,我没有得到我期望的结果。我应该使用sort方法吗?我应该单独比较mapping阵列的结果吗?

+1

的[排序由多个对象(由高到低)然后通过字母(字母)的集合(HTTP可能重复:// stackoverflow.com/questions/2232470/sort-a-collection-of-objects-by-number-highest-first-then-by-letter-alphabeti) – 2012-01-17 02:15:38

+1

@pruett:没有不尊重robbrit的回答,但你应该考虑选择回答,使用Enumerable#sort *没有任何问题,除了* Enumerable#sort_by完成这项工作时。这对于登陆这里的人来说可能会产生误导。 – tokland 2012-01-17 08:11:53

+0

可能重复[Ruby多值排序?](http://stackoverflow.com/questions/4309723/ruby-sort-by-multiple-values) – jtbandes 2016-11-08 05:21:45

回答

39

你应该总是使用sort_by为键控排序。它不仅更具可读性,而且更有效率的。另外,我也宁愿用解构绑定,再次,为便于阅读:

ary.sort_by {|name, age| [age, name] } 
+3

[解构绑定](http://stackoverflow.com/a/3952057/38765) – 2012-01-17 05:50:45

11

这应该做的伎俩:

array.sort { |a,b| [ a[1], a[0] ] <=> [ b[1], b[0] ] } 

那么这是什么呢?它使用了很多Ruby成语。

  • 首先是块,有点像回调或其他语言中的匿名函数/类。 Array的sort方法使用它们根据块的返回值比较两个元素。你可以阅读关于它们的所有内容here
  • 接下来是<=>运营商。如果第一个参数小于第二个参数,则返回-1,如果相等,则返回0,如果第一个参数大于第二个,则返回1。当你将它与数组一起使用时,它将比较数组元素,直到它们中的一个返回-1或1.如果数组相等,则会得到0.
+0

很好的解释...谢谢@robbrit。 – pruett 2012-01-17 00:18:54

+6

你也可以使用'sort_by {| a | [a [1],a [0]]}'构造所有这些数组并不是免费的。 – 2012-01-17 00:34:28

6

据我了解,您要订购按年龄第一,然后如果不止一个记录的年龄相同,则按名称排列该子集。


这对我的作品

people = [ 
     ["bob", 15, "male"], 
     ["alice", 25, "female"], 
     ["bob", 56, "male"], 
     ["dave", 45, "male"], 
     ["alice", 56, "female"], 
     ["adam", 15, "male"] 
    ] 

people.sort{|a,b| (a[1] <=> b[1]) == 0 ? (a[0] <=> b[0]) : (a[1] <=> b[1]) } 

# The sorted array is 

[["adam", 15, "male"], 
["bob", 15, "male"], 
["alice", 25, "female"], 
["dave", 45, "male"], 
["alice", 56, "female"], 
["bob", 56, "male"]] 

这是什么东西做的是按年龄第一次比较,如果年龄是相同的(< => returs 0)比较​​它的名字。

+0

非常好!我喜欢这种语法 – pruett 2012-01-17 01:18:03

+0

如果年龄相同,然后我们想按降序对名称进行排序,该怎么办? – inquisitive 2015-05-21 21:39:13

+0

@Inquisitive那么在这种情况下,我想你会在右边的“(a [1] <=> b [1])”中切换“a”和“b”。 – user1515295 2015-10-20 01:40:22