Forum: Ruby Ordered Hash (v. 1.8)

Posted by Doug Jolley (ddjolley)
on 2012-11-30 02:46
I am running Ruby v. 1.8.7 and I have installed the orderedhash gem.  I
know that the purpose of orderedhash is to preserve the order of
creation.  However, what I'd really like to do is, after the hash has
been created, sort it on the key in a manner similar to the way that I
would sort an array with the sort!() method and then preserve the sorted
order.  Any ideas on how I might accomplish that feat?  Thanks for any
input.

     ... doug
Posted by unknown (Guest)
on 2012-11-30 07:16
(Received via mailing list)
Am 30.11.2012 02:46, schrieb Doug Jolley:
> I am running Ruby v. 1.8.7 and I have installed the orderedhash gem.  I
> know that the purpose of orderedhash is to preserve the order of
> creation.  However, what I'd really like to do is, after the hash has
> been created, sort it on the key in a manner similar to the way that I
> would sort an array with the sort!() method and then preserve the sorted
> order.  Any ideas on how I might accomplish that feat?  Thanks for any
> input.
>
>       ... doug

1. You could use the RBTree gem.

2. Iterate through the sorted keys when you need to access elements
    in sorted order:

1.9.3p194 :001 > hash = {:c => 1, :a => 2, :b => 3}
  => {:c=>1, :a=>2, :b=>3}
1.9.3p194 :002 > sorted_keys = hash.keys.sort
  => [:a, :b, :c]
1.9.3p194 :003 > sorted_keys.each do |key|
1.9.3p194 :004 >     puts "#{key} => #{hash[key]}"
1.9.3p194 :005?>   end
a => 2
b => 3
c => 1
  => [:a, :b, :c]
Posted by Harry Kakueki (Guest)
on 2012-11-30 07:20
(Received via mailing list)
> creation.  However, what I'd really like to do is, after the hash has
> been created, sort it on the key in a manner similar to the way that I
> would sort an array with the sort!() method and then preserve the sorted
> order.  Any ideas on how I might accomplish that feat?  Thanks for any
> input.
>
>      ... doug


Does this work?


h = {}
arr = ["t","c","h","b","l"]
arr.each{|x| h[x] = x + "ook"}

h = Hash[h.sort]
p h   #> {"b"=>"book", "c"=>"cook", "h"=>"hook", "l"=>"look", 
"t"=>"took"}



Harry
Posted by unknown (Guest)
on 2012-11-30 07:23
(Received via mailing list)
Am 30.11.2012 07:15, schrieb sto.mar@web.de:
>
> 1.9.3p194 :004 >     puts "#{key} => #{hash[key]}"
> 1.9.3p194 :005?>   end
> a => 2
> b => 3
> c => 1
>   => [:a, :b, :c]

correction: in 1.8, when your keys are symbols you need to sort with

   sorted_keys = hash.keys.sort_by(&:to_s)
Posted by unknown (Guest)
on 2012-11-30 07:29
(Received via mailing list)
Am 30.11.2012 07:19, schrieb Harry Kakueki:
>
>
> h = {}
> arr = ["t","c","h","b","l"]
> arr.each{|x| h[x] = x + "ook"}
>
> h = Hash[h.sort]
> p h   #> {"b"=>"book", "c"=>"cook", "h"=>"hook", "l"=>"look", "t"=>"took"}

not in Ruby 1.8!

And in 1.9 you would have to recreate the complete hash for
each key-value pair that is added.
Posted by unknown (Guest)
on 2012-11-30 07:35
(Received via mailing list)
Am 30.11.2012 07:22, schrieb sto.mar@web.de:
>>>       ... doug
You can access the elements in sorted order even more easily like this:

   hash = {:c => 1, :a => 2, :b => 3}

   hash.sort_by(&:to_s).each do |k, v|
     puts "#{k} => #{v}"
   end

output:

a => 2
b => 3
c => 1
Posted by Harry Kakueki (Guest)
on 2012-11-30 08:10
(Received via mailing list)
> I am running Ruby v. 1.8.7 and I have installed the orderedhash gem.  I
> know that the purpose of orderedhash is to preserve the order of
> creation.  However, what I'd really like to do is, after the hash has
> been created, sort it on the key in a manner similar to the way that I
> would sort an array with the sort!() method and then preserve the sorted
> order.  Any ideas on how I might accomplish that feat?  Thanks for any
> input.
>
>      ... doug


# If you want to also keep the original order, maybe this is worth a 
look.
# I'm using 1.9 so I can't test it for your setup.

class Hash
  def myway
    Hash[*sort.flatten]  #Ruby 1.8 ?
    #Hash[sort]   # Ruby1.9
  end
end

h = {}
arr = ["t","c","h","b","l"]
arr.each{|x| h[x] = x + "ook"}

p h                #>  {"t"=>"took", "c"=>"cook", "h"=>"hook",
"b"=>"book", "l"=>"look"}
p h.myway  #>  {"b"=>"book", "c"=>"cook", "h"=>"hook", "l"=>"look", 
"t"=>"took"}


Harry
Posted by unknown (Guest)
on 2012-11-30 15:35
(Received via mailing list)
Am 30.11.2012 08:09, schrieb Harry Kakueki:

> # If you want to also keep the original order, maybe this is worth a look.
> # I'm using 1.9 so I can't test it for your setup.
>
> class Hash
>    def myway
>      Hash[*sort.flatten]  #Ruby 1.8 ?
>      #Hash[sort]   # Ruby1.9
>    end
> end

This does not work in 1.8, because hashes in 1.8 do
*not* keep the insertion order.
Posted by Robert Klemme (robert_k78)
on 2012-11-30 16:11
(Received via mailing list)
On Fri, Nov 30, 2012 at 3:34 PM,  <sto.mar@web.de> wrote:
>>    end
>> end
>
>
> This does not work in 1.8, because hashes in 1.8 do
> *not* keep the insertion order.

That's why Doug had installed the OrderedHash Gem I guess.  So with a
little change that should work:

# untested:
OrderedHash[*sort.flatten]

Kind regards

robert
Posted by Thomas Sawyer (7rans)
on 2012-11-30 18:47
(Received via mailing list)
On Thursday, November 29, 2012 8:46:48 PM UTC-5, Doug Jolley wrote:
>
> I am running Ruby v. 1.8.7 and I have installed the orderedhash gem.  I
> know that the purpose of orderedhash is to preserve the order of
> creation.  However, what I'd really like to do is, after the hash has
> been created, sort it on the key in a manner similar to the way that I
> would sort an array with the sort!() method and then preserve the sorted
> order.  Any ideas on how I might accomplish that feat?  Thanks for any
> input.
>

You can use Hashery's Disctionary class.

  $ gem install hashery

Then code:

  require 'hashery/dictionary'

  dict = Hashery::Dictionary.new_by{ |k,v| k }
Posted by Doug Jolley (ddjolley)
on 2012-12-03 01:12
Thanks to all who contributed in this thread. Using your valuable 
contributions, I was able to solve my problem.  The final solution was 
not at all what I had in mind when I posted my original post.  Thanks to 
the guidance obtained from this thread, I was able to accomplish my 
objective by using the sort method of a traditional hash (i.e., I did 
not need the ordered hash as I thought that I would).  Thanks for 
getting me pointed in the right direction.

      ... doug
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.