Skip to content
trans edited this page Mar 16, 2012 · 1 revision

SlashedHash

The concept of a SlashedHash is to flatten down a multi-level Hash structure into a single-level Hash whose keys represent the pathway to the data in the original multi-level structure. For example,

>> sh = {'a' => 'b', 'c' => {'d' => :e, 'f' => ['a', 'b']}, 'd' => ['e', 'f']}.slashed
=> {slashed: "a"=>"b", "c/d"=>:e, "d"=>["e", "f"], "c/f"=>["a", "b"]}

Once you transform a Hash into a SlashedHash, the only negative differences are:

  1. All but the end-point (or 'leaf node') data are turned into strings. Restated: Any data at the "end" of a Hash multi-level structure is left alone, but all keys in between, whether string, symbol, or anything else, is turned into a string in order to pack them together into a "slashed" key.

  2. Speed. A Ruby Hash is built into the core and written mostly in C so it is very fast; but a SlashedHash clones the same C functionality on all the Hash's methods so that it can act as a normal Hash but with more sugar.

Like I said, the above mentioned things are the only negative differences. You can still access items by their original keys -- to continue the example above,

>> sh['c']['d']
=> :e

BUT you can also access the same values by their "slashed" keys:

>> sh['c/d']
=> :e
>> sh['c/f']
=> ["a", "b"]

And you can access the keys either normally or flattened:

>> sh.keys
=> ["a", "c", "d"]
>> sh.flat.keys
=> ["a", "c/d", "d", "c/f"]

Accessing one level into the SlashedHash gives you another SlashedHash, if applicable:

>> sh['c']
=> {slashed: "d"=>:e, "f"=>["a", "b"]}

What good is SlashedHash? What can it do for me?

  1. It comes in VERY handy when doing special transformations or multi-level key mappings. Think of reading an XML structure into specific property names (example uses the formattedstring gem syntax):

    joe = "Joe Schmoe25Joseph Schmoe56".formatted(:xml).to_hash.slashed => {slashed: "person"=>{"name"=>"Joe Schmoe", "age"=>"25", "parent"=>{"name"=>"Joseph Schmoe", "age"=>"56"}}} mapping = {'name' => 'person/name', 'age' => 'person/age', 'parent_name' => 'person/parent/name', 'parent_age' => 'person/parent/age'} joe.transform_keys_with_mapping(mapping) => {"name"=>"Joe Schmoe", "parent_name"=>"Joseph Schmoe", "age"=>"25", "parent_age"=>"56"}

  2. It is useful for sorting multi-level hashes by integration with OrderedHash.

...

Clone this wiki locally