Reputation: 390
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
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
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
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