开发者

Ruby sort by multiple values?

开发者 https://www.devze.com 2023-01-28 14:43 出处:网络
I have an array of hashes: a=[{ \'foo\'=>0,\'bar\'=>1 }, { \'foo\'=>0,\'bar\'=>2开发者_如何学C },

I have an array of hashes:

a=[{ 'foo'=>0,'bar'=>1 },
   { 'foo'=>0,'bar'=>2开发者_如何学C },
   ... ]

I want to sort the array first by each hash's 'foo', then by 'bar'. Google tells me this is how it's done:

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

But this gives me the ArgumentError "comparison of Array with Array failed". What does this mean?


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


It probably means you're missing one of the fields 'foo' or 'bar' in one of your objects.

The comparison is coming down to something like nil <=> 2, which returns nil (instead of -1, 0 or 1) and #sort_by doesn't know how to handle nil.

Try this:

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


What you have posted works in 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}] 


This exception occurs when the result array used for the comparison contains both nil and non-nil values.


This error appeares when you have unstable keys and trying to sort by them. Example:

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

Try to do

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

But it doesnt work for me in

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

where digit is unstable


comparison of Array with Array failed

This means (at least in my case) that the types of array elements are different. When I made sure all array items are of the same time (Integer, for example), sorting started to work.


consider compacting the array (removing nil entries), and as a bonus, if it's string comparision, downcase the values for case insensitive sorting.

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


I was working on a task where I needed to sort array of hashes by different keys and different directions (by first key ascending, by second descending and etc.)

I've created this helper class, called it AwesomeSort because it's awesome and it's written in Ruby.

https://gist.github.com/pucinsk/36ffef881622b2d9dcca6716f403dc27

0

精彩评论

暂无评论...
验证码 换一张
取 消