Cristiano
Cristiano

Reputation: 2909

Sort in ruby a JSON array of hashes

So I have an array of hashes:

[{"id":"30","name":"Dave"},
 {"id":"57","name":"Mike"},
 {"id":"9","name":"Kevin"},
 ...
 {"id":"1","name":"Steve"}]

And I want to sort it by the id attribute, so that it looks like this:

[{"id":"1","name":"Steve"},
 {"id":"2","name":"Walter"},
 ...
 {"id":"60","name":"Chester"}]

I'm assuming I use the sort_by method but I'm not exactly sure how to do it.

Upvotes: 8

Views: 14727

Answers (3)

the Tin Man
the Tin Man

Reputation: 160631

When I see incoming data like that, it's almost always a JSON string. Ruby doesn't automatically understand JSON, nor does it automatically know how to convert it, but Ruby does make it easy for us to convert from/to it:

require 'json'

json_data = '[{"id":"30","name":"Dave"},
 {"id":"57","name":"Mike"},
 {"id":"9","name":"Kevin"},
 {"id":"1","name":"Steve"}]'

ary = JSON[json_data].sort_by{ |e| e['id'].to_i }
ary 
# => [{"id"=>"1", "name"=>"Steve"}, {"id"=>"9", "name"=>"Kevin"}, {"id"=>"30", "name"=>"Dave"}, {"id"=>"57", "name"=>"Mike"}]

The only real trick here is:

JSON[json_data]

A lot of time you'll see people use JSON.parse(json_data), but the [] method is smart enough to recognize whether it's getting a String or an array or a hash. If it's a string it tries to parse it assuming it's incoming data. If it's an array or a hash, it converts it to a JSON string for output. The result is, using JSON[...] simplifies the use of the class and makes it so we don't have to use parse or to_json.

Otherwise, using sort_by is preferred over using sort unless you are directly comparing two simple variables, like integer to integer, string to string or character to character. Once you have to dive into an object, or do some sort of calculation to determine how things compare, then you should use sort_by. See Wikipedia's article on Schwartzian Transform to understand what's going on under the covers. It's a very powerful technique that can speed up sorting remarkably.

Upvotes: 6

Marek Lipka
Marek Lipka

Reputation: 51191

This should work:

array.sort_by { |hash| hash['id'].to_i }

In this case, sort_by is preferred over sort because it is more efficient. While sort calls to_i on every comparison, sort_by does it once for each element in array and remembers the result.

Upvotes: 22

hirolau
hirolau

Reputation: 13921

Your Hash syntax is wrong, if they where symbols then it would look like this:

data = [
  {id:"30", name:"Dave"},
  {id:"57", name:"Mike"},
  {id:"9", name:"Kevin"},
  {id:"1", name:"Steve"}
] 
sorted_data = data.sort_by{|x| x[:id].to_i}

Edit: Forgot the to_i, fixed. If the keys are strings the : way of defining a hash does not work, so we need hash-rockets instead:

data = [{"id"=>"30","name"=>"Dave"},
 {"id"=>"57","name"=>"Mike"},
 {"id"=>"9","name"=>"Kevin"},
 {"id"=>"1","name"=>"Steve"}]

sorted_data = data.sort_by{|x| x['id'].to_i}

Upvotes: 2

Related Questions