8

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.

4
  • The way you have defined a hash is not legal in ruby. Use symbols or hash-rockets. Commented Oct 28, 2013 at 13:44
  • 1
    That is a JSON array of hashes. Commented Oct 28, 2013 at 13:49
  • 2
    True, but as he is asking about how to sort the array in Ruby, It would make much more sense to use Ruby syntax. Commented Oct 28, 2013 at 14:02
  • 4
    Yes it would, and saying the hash syntax is wrong will be confusing. Answers should show how to convert from JSON to Ruby to close the gap. Don't just hand out fish, teach how to fish. Commented Oct 28, 2013 at 14:07

3 Answers 3

22

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Gee, that sounds just like what I said in a comment. Couldn't you paraphrase it better?
@theTinMan answer with your comment was already deleted when I was editing my answer and I gave it only short glance until then. So I don't feel guilty. :)
6

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.

Comments

2

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}

4 Comments

You should convert string ids to integers. Hint: '30' < '4'.
And, it's unlikely that the hashes in original array are instances of HashWithIndifferentAccess, so accessing ids with symbols probably won't work.
As the person asking the question define the hash in some kind if mixed way between the hash-rocket and the new symbol-way it is hard to know what they kind of class the keys are. Added both cases to my answer.
The original array of hashes is a JSON array of hashes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.