«

»

Oct
02

Ordered Hash by keys

Recently, I have to implement my own Hash sorting method. Not really with Hash but with ActiveSupport::OrderedHash

      I don’t like the way ActiveSupport::OrderedHash behaves with sorting functionality.
      It just behaves like a simple Hash
      I would like that sort return an ActiveSupport::OrderedHash not an Arrray!!! Why is it called OrderedHash in this case ?
      I would like to sort with keys only, not with an array [key, value]

Ok no matter, I implemented my own new SimpleOrderedHash :

require 'active_support/ordered_hash'
class SimpleOrderedHash < ActiveSupport::OrderedHash
 
  # Lets reimplement sort method
  def sort(&block)
    h = self.dup
    h.sort!(&block)
    h
  end
 
  # Lets implement sort! method
  # It uses @keys variable to do the sorting
  def sort!(&block)
    @keys.sort!(&block)
    sync_keys!
    self
  end
 
  # A fancy inspect   
  def inspect
    "#<#{self.class.name} #{Hash.instance_method(:inspect).bind(self).call}>"
  end
end

You can now use it like that :

h = SimpleOrderedHash.new
h.merge!({'second' => 1, 'first' => 5, 'third' => 2.5})
=> #<SimpleOrderedHash {"third"=>2.5, "second"=>1, "first"=>5}>
 
# sort return a SimpleOrderedHash
result = h.sort do |a,b|
  h[a] <=> h[b]
end
=> #<SimpleOrderedHash {"third"=>2.5, "second"=>1, "first"=>5}>
 
# and order as I wanted
result.each{ |k,v| puts v }
1
2.5
5
=> ["second", "third", "first"]
 
# sort! change internally the order of a SimpleOrderedHash
h.sort! do |a,b|
  h[b] <=> h[a]
end
h.each{ |k,v| puts v }
5
2.5
1
=> ["first", "third", "second"]

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">