开发者

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:

  1. a new entry has a key that is in range (<= the largest current key).
  2. 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.
  3. Insert new Entry

Delete: When an entry is deleted, decrement the key value for all keys > the deletion value.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜