Ruby按多个值排序?


78

我有一系列哈希:

a=[{ 'foo'=>0,'bar'=>1 },
   { 'foo'=>0,'bar'=>2 },
   ... ]

我想先按每个哈希的“ foo”对数组进行排序,然后再按“ bar”对数组进行排序。Google告诉我这是怎么做的:

a.sort_by {|h| [ h['foo'],h['bar'] ]}

但这给了我ArgumentError“比较数组与数组失败”。这是什么意思?


3
为我工作。您使用的是旧版本的红宝石吗?
亚历克斯·韦恩

2
您发布的内容适用于1.8.7。
Phrogz

1
您认为您拥有的数据与实际拥有的数据是否可能不相同?
韦恩·康拉德

24
当用于比较的结果数组同时包含nil和nonnil值时,将发生此异常。
gucki 2012年

还要注意,Ruby无法比较布尔值,这也可能导致此错误。
amoebe

Answers:


83
a.sort { |a, b| [a['foo'], a['bar']] <=> [b['foo'], b['bar']] }

11
这是同一回事。Enumerable#sort_by(&block)大致而言sort { |a,b| block.call(a) <=> block.call(b) },除非以更有效的方式完成。如果这有效但sort_by不起作用,则意味着其他问题。
wuputah

对于简单的键,排序效率更高。对于复杂的键,sort_by效率更高。
dj2

1
嗯,现在我得到的是“当您没想到时,您有一个零对象!” 错误。我使用的确切数组是a=[{'foo'=>0,'bar'=>2},{'foo'=>0,'bar'=>1},{'foo'=>2,'bar'=>1},{'foo'=>1,'bar'=>0}]
herpderp 2010年

对我有用。>> a = [{''foo'=> 0,'bar'=> 2},{'foo'=> 0,'bar'=> 1},{'foo'=> 2,' bar'=> 1},{'foo'=> 1,'bar'=> 0}] => [{“ foo” => 0,“ bar” => 2},{“ foo” => 0, “ bar” => 1},{“ foo” => 2,“ bar” => 1},{“ foo” => 1,“ bar” => 0}] >> a.sort {| a,b | [a ['foo'],a ['bar']] <=> [b ['foo'],b ['bar']]} => [{“ foo” => 0,“ bar” => 1},{“ foo” => 0,“ bar” => 2},{“ foo” => 1,“ bar” => 0},{“ foo” => 2,“ bar” => 1} ]
dj2

6
sort_by的优点之一是它更干燥。
安德鲁·格林

24

这可能意味着您在其中一个对象中缺少字段“ foo”或“ bar”之一。

比较已大幅下降,喜欢的东西nil <=> 2,它的回报nil(而不是-101)和#sort_by不知道如何处理nil

试试这个:

a.sort_by {|h| [ h['foo'].to_i, h['bar'].to_i ]}

13

您发布的内容在Ruby 1.8.7中有效:

ruby-1.8.7-p302 > a = [{'foo'=>99,'bar'=>1},{'foo'=>0,'bar'=>2}]
 => [{"foo"=>99, "bar"=>1}, {"foo"=>0, "bar"=>2}] 

ruby-1.8.7-p302 > a.sort_by{ |h| [h['foo'],h['bar']] }
 => [{"foo"=>0, "bar"=>2}, {"foo"=>99, "bar"=>1}] 

ruby-1.8.7-p302 > a.sort_by{ |h| [h['bar'],h['foo']] }
 => [{"foo"=>99, "bar"=>1}, {"foo"=>0, "bar"=>2}] 


1

当您有不稳定的键并尝试按它们排序时,会出现此错误。例:

[{'foo'=>99,'bar'=>1},{'foo'=>0,'bar'=>2, 'qwe' => 7}]
a.sort_by{|v| v['qwe']}
ArgumentError: comparison of NilClass with 7 failed

试着做

a.sort_by{|v| [v['qwe']].select{|k| not k.nil?}}

但这对我不起作用

[v['index'],v['count'],v['digit'],v['value']]

数字不稳定的地方


1

数组与数组比较失败

这意味着(至少在我看来)数组元素的类型不同。当我确定所有数组项目都在同一时间(Integer例如)时,排序开始起作用。


0

考虑压缩数组(删除nil项),并且,如果是字符串比较,则可以减小大小写,以区分大小写。

a.compact.sort_by { |h| [h['foo'].downcase, h['bar'].downcase] }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.