ruby - guarantee order of keys in hash after much manipulation -


here's problem. going through these steps below can see how hash keys no longer in order. in below example, keys 0, 2, rather 0,1. , sure larger data set, situation worse. there way can guarantee order of keys in hash?

task:

  1. if fields has defaults doesn't have, add defaults
  2. if defaults has key k field not have, remove key-value pair key k default

test data:

fields = { "0"=>{"field"=>"name", "field_type_id"=>1}, "1"=>{"field"=>"address", "field_type_id"=>2} } defaults = {0=>"name", 1=>"email" }  

step 1: find ones in fields not in defaults:

fields_arr = fields.values.collect {|hsh| hsh['field'] }   => ["name", "address"] defaults_arr = defaults.values => ["name", "email"] updates = fields_arr + defaults_arr - (fields_arr & defaults_arr) - defaults_arr => ["address"] 

step 2: update defaults new fields, key starts last key of defaults:

i = defaults.keys.last.to_i + 1 additions = updates.reduce({}) |acc, n|   acc[i] = n   += 1   acc        end defaults.merge!(additions) => {0=>"name", 1=>"email", 2=>"address"} 

step 3: remove defaults no longer exists in fields. (in other words, have remove "email" in example):

defaults => {0=>"name", 1=>"email", 2=>"address"} defaults_arr = defaults.values removals = fields_arr + defaults_arr - (fields_arr & defaults_arr) => ["email"] defaults.delete_if{|_,v| removals.include? v } => {0=>"name", 2=>"address"}  

a hash ordered, doesn't mean it's sorted; there's big difference. it's ordered because insertion order of key/value pairs remembered. documentation says:

hashes enumerate values in order corresponding keys inserted.

sorting hash nonsensical; nothing speed access or insertion speed, and, if insist on maintaining sort order in hash modify it, you're wasting cpu time.

think of them if random access devices, such in-memory database when reading/writing records. can jump around without real speed penalty , find things, insert new ones, or update them. having them in sorted order makes no real difference @ point.

if need retrieve keys or associated values in particular order, then, after you're finished modifying hash, extract keys using keys, order resulting array iterate on or use values_at or order result of values:

foo = {   'z' => 26,   'a' => 1 }  sorted_keys = foo.keys.sort # => ["a", "z"] foo.values_at(*sorted_keys) # => [1, 26] reverse_sorted_keys = foo.keys.sort.reverse # => ["z", "a"] foo.values_at(*reverse_sorted_keys) # => [26, 1] foo.values.sort # => [1, 26] foo.values.sort.reverse # => [26, 1] 

i'd recommend reading "sort hash key, return hash in ruby" , answers more information.


Comments

Popular posts from this blog

Java 3D LWJGL collision -

spring - SubProtocolWebSocketHandler - No handlers -

methods - python can't use function in submodule -