-
Notifications
You must be signed in to change notification settings - Fork 4
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:
-
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.
-
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"]}
-
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"}
-
It is useful for sorting multi-level hashes by integration with OrderedHash.
...