Is possible to insert a new item in the middle of a hash and have it reindex?
I have this as a hash :
>> params[:payments]
{"0"=>{":amount_paid"=>"100.00", ":date_paid"=>"2/20/2009开发者_JAVA百科"}}
{"1"=>{":amount_paid"=>"100.00", ":date_paid"=>"2/20/2009"}}
{"2"=>{":amount_paid"=>"100.00", ":date_paid"=>"2/20/2009"}}
Is it possible to make a new hash and insert it into a specific place ? For example, take this line :
{"2"=>{":amount_paid"=>"1.00", ":date_paid"=>"1/1/2006"}}
So that the hash will appear as this now :
{"0"=>{":amount_paid"=>"100.00", ":date_paid"=>"2/20/2009"}}
{"1"=>{":amount_paid"=>"1.00", ":date_paid"=>"1/1/2006"}} # <-- Newly inserted line
{"2"=>{":amount_paid"=>"100.00", ":date_paid"=>"2/20/2009"}}
{"3"=>{":amount_paid"=>"100.00", ":date_paid"=>"2/20/2009"}}
Try using an Array, as hashes are not inherently ordered. Ruby's Array.insert lets you specify where to insert your new objects (http://www.ruby-doc.org/core/classes/Array.html#M000230), and using your example above, we get:
arr = [{":amount_paid"=>"100.00", ":date_paid"=>"2/20/2009"},
{":amount_paid"=>"100.00", ":date_paid"=>"2/20/2009"},
{":amount_paid"=>"100.00", ":date_paid"=>"2/20/2009"}]
arr.insert(2, {"some hash"})
[{":amount_paid"=>"100.00", ":date_paid"=>"2/20/2009"},
{":amount_paid"=>"100.00", ":date_paid"=>"2/20/2009"},
{"some hash"},
{":amount_paid"=>"100.00", ":date_paid"=>"2/20/2009"}]
You can then iterate over the indices and maintain your desired order while adding to it.
In Ruby 1.9+, Hashes are not ordered, instead, they maintain the order that entries are inserted:
From the docs:
Hashes enumerate their values in the order that the corresponding keys were inserted.
require 'pp'
hash = {
'a' => 1,
'c' => 3
}
hash['b'] = 2
pp hash
# >> {"a"=>1, "c"=>3, "b"=>2}
As an alternate to sorting the hash keys then iterating over the hash, the hash itself can be sorted, then regenerated if you want to walk it directly:
ruby-1.9.2-p136 :010 > Hash[*hash.sort.flatten]
=> {"a"=>1, "b"=>2, "c"=>3}
Use it like:
hash = Hash[*hash.sort.flatten]
It's probably faster with a big hash to sort the keys then walk them, but if you gotta have the hash in order that will do it.
If you had to do this with a Hash, and you didn't want to use the index of an array, you would create a new class, OrderedHash. In that class, you need to create an insert
and delete
method that enforces the following properties:
Insert:
- a new entry has a key that is in range (<= the largest current key).
- If a new entry has a key that is already used, for each number from the current new key value to the largest value, increment the key value by one. Probably best to do this from the largest down to the smallest to avoid problems.
- Insert new Entry
Delete: When an entry is deleted, decrement the key value for all keys > the deletion value.
精彩评论