How to sort a hash by value in descending order and output a hash in ruby?
Try:
Hash[h.sort.reverse]
This should return what you want.
Edit:
To do it by value:
Hash[h.sort_by{|k, v| v}.reverse]
Sort array of hashes by value of hash property in descending order preserving the initial order of hash
results = [
{ "rating"=>6, "id"=>10699 },
{ "rating"=>3, "id"=>19985 },
{ "rating"=>6, "id"=>1029 }
]
results.sort_by.with_index { |h,i| [-h["rating"], i] }
#=> [{"rating"=>6, "id"=>10699},
# {"rating"=>6, "id"=>1029}
# {"rating"=>3, "id"=>19985}]
See the third paragraph of the doc Array#<=> for an explanation of how Ruby orders arrays. When Ruby orders results[0]
and results[2]
she compares [-6, 0]
with [-6, 2]
. Because the first elements of these arrays are equal (-6
), Ruby compares 0
with 2
to break the tie, so results[0]
is ordered before results[2]
.
Note that when the method Enumerable#sort_by has no block, it returns an enumerator. Here that enumerator is chained to Enumerator#with_index to produce another enumerator.
Sorting Hash by value
Enumerable#sort_by
never promised to sort the enumerable inplace. It returns the result:
puts mapa.sort_by {|a,b| -b}
#⇒ sorted
or, in more idiomatic manner:
mapa.sort_by(&:last).reverse.each do |k, v|
puts ...
end
Please note, that when examining the output in irb
, the order might not correspond to the real order of elements in a hash, since irb
(with print formatters installed) has it’s own ideas on how to output hashes.
How to sort a Ruby Hash by number value?
No idea how you got your results, since it would not sort by string value... You should reverse a1
and a2
in your example
Best way in any case (as per Mladen) is:
metrics = {"sitea.com" => 745, "siteb.com" => 9, "sitec.com" => 10 }
metrics.sort_by {|_key, value| value}
# ==> [["siteb.com", 9], ["sitec.com", 10], ["sitea.com", 745]]
If you need a hash as a result, you can use to_h
(in Ruby 2.0+)
metrics.sort_by {|_key, value| value}.to_h
# ==> {"siteb.com" => 9, "sitec.com" => 10, "sitea.com", 745}
Descending sort by value of a Hash in Ruby
You can have it cleaner, clearer and faster, all at once! Like this:
h.sort_by {|k,v| v}.reverse
I benchmarked timings on 3000 iterations of sorting a 1000-element hash with random values, and got these times:
h.sort {|x,y| -(x[1]<=>y[1])} -- 16.7s
h.sort {|x,y| y[1] <=> x[1]} -- 12.3s
h.sort_by {|k,v| -v} -- 5.9s
h.sort_by {|k,v| v}.reverse -- 3.7
Sort array of hash by key in descending order in Ruby
You can do
h.sort_by! { |k| -k[:bookings_nd] }
or
h.sort_by! { |k| k[:bookings_nd] }.reverse!
Also i guess this question is duplicate for Sorting an array in descending order in Ruby
Sort hash by length of values (descending)
You cannot sort a hash - that might be causing your confusion. There is no "internal" ordering of elements of a hash as it appears in an array.
You can, however, iterate over a hash in a certain order, e.g.
hash.sort_by {|k,v| v.length}.reverse.each do |k, v|
puts "k = #{k}, v = #{v}"
end
How to sort a Ruby Hash alphabetically by keys
Assuming you want the output to be a hash which will iterate through keys in sorted order, then you are nearly there. Hash#sort_by
returns an Array
of Array
s, and the inner arrays are all two elements.
Ruby's Hash
has a constructor that can consume this output.
Try this:
temp = Hash[ temp.sort_by { |key, val| key } ]
or more concisely
temp = temp.sort_by { |key| key }.to_h
If your hash has mixed key types, this will not work (Ruby will not automatically sort between String
s and Symbol
s for instance) and you will get an error message like comparison of Symbol with String failed (ArgumentError). If so, you could alter the above to
temp = Hash[ temp.sort_by { |key, val| key.to_s } ]
to work around the issue. However be warned that the keys will still retain their original types which could cause problems with assumptions in later code. Also, most built-in classes support a .to_s
method, so you may get unwanted results from that (such as unexpected sort order for numeric keys, or other unexpected types).
You could, in addition, convert the keys to Strings
with something like this:
temp = Hash[ temp.map { |key, val| [key.to_s, val] }.sort ]
. . . although this approach would lose information about the type of the original key making it impossible to refer back to the original data reliably.
Ruby sort by hash and value
Enumerable#sort_by
to the rescue:
hash_data.sort_by { |hash| hash[:sortby] }
#=> [{:key1=>"valuedsd", :sortby=>1}, {:key1=>"value2_data_is_here", :sortby=>2}, {:key1=>"value4", :sortby=>4}, {:key1=>"valuesds6", :sortby=>6}]
If you don't care about initial object, I would suggest using Array#sort_by!
to modify inplace - it is more resource-efficient:
hash_data.sort_by! { |hash| hash[:sortby] }
If you have different types of data as values to sortby
key, you should first unify the data type and only then perform sorting.
To have array sorted in descending order, use Enumerable#reverse
(or reverse!
):
hash_data.sort_by {|hash| hash[:sortby] }.reverse
#=> [{:key1=>"valuesds6", :sortby=>6}, {:key1=>"value4", :sortby=>4}, {:key1=>"value2_data_is_here", :sortby=>2}, {:key1=>"valuedsd", :sortby=>1}]
Another option for sorting in descending order is the following - note minus sign (credits to @sagarpandya82):
hash_data.sort_by {|hash| -hash[:sortby] }
Related Topics
Rails 5.2.0 with Ruby 2.5.1 Console - 'Warning:' 'Already' Initialized Constant Fileutils::Version
Best Place to Store Model Specific Constants in Rails 3.1
How to Write Specs for Code That Depends on Environment Variables
How to Check If a Gem Is Installed
How to Run Ruby Tasks That Use My Rails Models
Rails 3 Initializes Extremely Slow on Ruby 1.9.2
How to Switch to Older Versions of the Ruby/Rails Environment
Ruby: Put Request with JSON Body
Array.Include? Multiple Values
When Is It Better to Use a Struct Rather Than a Hash in Ruby
Ruby: How to Count the Number of Times a String Appears in Another String
How to Declare a Variable Shared Between Examples in Rspec
How to Use Nokogiri to Parse an Xml File