Sort hash by key, return hash in Ruby

前端 未结 10 1364
时光取名叫无心
时光取名叫无心 2020-11-27 10:05

Would this be the best way to sort a hash and return Hash object (instead of Array):

h = {\"a\"=>1, \"c\"=>3, \"b\"=>2, \"d\"=>4}
# => {\"a\"=         


        
相关标签:
10条回答
  • 2020-11-27 10:37

    No, it is not (Ruby 1.9.x)

    require 'benchmark'
    
    h = {"a"=>1, "c"=>3, "b"=>2, "d"=>4}
    many = 100_000
    
    Benchmark.bm do |b|
      GC.start
    
      b.report("hash sort") do
        many.times do
          Hash[h.sort]
        end
      end
    
      GC.start
    
      b.report("keys sort") do
        many.times do
          nh = {}
          h.keys.sort.each do |k|
            nh[k] = h[k]
          end
        end
      end
    end
    
           user     system      total        real
    hash sort  0.400000   0.000000   0.400000 (  0.405588)
    keys sort  0.250000   0.010000   0.260000 (  0.260303)
    

    For big hashes difference will grow up to 10x and more

    0 讨论(0)
  • 2020-11-27 10:39

    Note: Ruby >= 1.9.2 has an order-preserving hash: the order keys are inserted will be the order they are enumerated. The below applies to older versions or to backward-compatible code.

    There is no concept of a sorted hash. So no, what you're doing isn't right.

    If you want it sorted for display, return a string:

    "{" + h.sort.map{|k,v| "#{k.inspect}=>#{v.inspect}"}.join(", ") + "}"
    

    or, if you want the keys in order:

    h.keys.sort
    

    or, if you want to access the elements in order:

    h.sort.map do |key,value|
      # keys will arrive in order to this block, with their associated value.
    end
    

    but in summary, it makes no sense to talk about a sorted hash. From the docs, "The order in which you traverse a hash by either key or value may seem arbitrary, and will generally not be in the insertion order." So inserting keys in a specific order into the hash won't help.

    0 讨论(0)
  • 2020-11-27 10:42

    In Ruby 2.1 it is simple:

    h.sort.to_h
    
    0 讨论(0)
  • 2020-11-27 10:45

    I had the same problem ( I had to sort my equipments by their name ) and i solved like this:

    <% @equipments.sort.each do |name, quantity| %>
    ...
    <% end %>
    

    @equipments is a hash that I build on my model and return on my controller. If you call .sort it will sort the hash based on it's key value.

    0 讨论(0)
提交回复
热议问题