Kavincat
Kavincat

Reputation: 390

How to sort hash in rails

I have a hash

x= {
  "1"=>{:name=>"test1", :age=>"1"}, 
  "5"=>{:name=>"test2", :age=>"5"}, 
  "2"=>{:name=>"test3", :age=>"2"}, 
  "4"=>{:name=>"test4", :adn=>"4"}, 
  "3"=>{:name=>"test5", :adn=>"3"}
 }

Desired output

x= {
  "1"=>{:name=>"test1", :age=>"1"}, 
  "2"=>{:name=>"test3", :age=>"2"}, 
  "3"=>{:name=>"test5", :age=>"3"}, 
  "4"=>{:name=>"test4", :adn=>"4"}, 
  "5"=>{:name=>"test2", :adn=>"5"}
 }

What I have so far, I tried doing x.sort.flatten and i got

[
  "1", {:name=>"test1", :age=>"1"}, 
  "2", {:name=>"test3", :age=>"2"}, 
  "3", {:name=>"test5", :adn=>"3"}, 
  "4", {:name=>"test4", :adn=>"4"}, 
  "5", {:name=>"test2", :age=>"5"}
]

Upvotes: 8

Views: 7723

Answers (3)

khiav reoy
khiav reoy

Reputation: 1403

You almost do it, just replace flatten with to_h

x.sort.to_h
# => {"1"=>{:name=>"test1", :age=>"1"}, "2"=>{:name=>"test3", :age=>"2"}, "3"=>{:name=>"test5", :adn=>"3"}, "4"=>{:name=>"test4", :adn=>"4"}, "5"=>{:name=>"test2", :age=>"5"}} 

Works in ruby 2.1.8

Upvotes: 2

Cary Swoveland
Cary Swoveland

Reputation: 110675

Here are some other ways of doing that.

x.keys.sort_by(&:to_i).each_with_object({}) { |k,h| h[k] = x[k] }
  #=> {"1"=>{:name=>"test1", :age=>"1"},
  #    "2"=>{:name=>"test3", :age=>"2"},
  #    "3"=>{:name=>"test5", :adn=>"3"},
  #    "4"=>{:name=>"test4", :adn=>"4"},
  #    "5"=>{:name=>"test2", :age=>"5"}} 

or

k = x.keys.sort_by(&:to_i)
k.zip(x.values_at(*k)).to_h

and if x is to be modified,

x.keys.sort_by(&:to_i).each { |k| x[k] = x.delete(k) }
x

Upvotes: 1

Eric Duminil
Eric Duminil

Reputation: 54223

I don't think it's possible to sort a hash directly. Converting to a sorted array and back again :

x.sort_by{ |key,_| key.to_i }.to_h

It outputs :

=> {"1"=>{:name=>"test1", :age=>"1"},
 "2"=>{:name=>"test3", :age=>"2"},
 "3"=>{:name=>"test5", :adn=>"3"},
 "4"=>{:name=>"test4", :adn=>"4"},
 "5"=>{:name=>"test2", :age=>"5"}}

If you want to sort by age :

x.sort_by{|k,v| v[:age].to_i}.to_h

If you want to sort by age or adn (in case it wasn't a typo) :

x.sort_by{|k,v| ( v[:age] || v[:adn] ).to_i}.to_h

Upvotes: 3

Related Questions