Get all leaves of a Hash (like recursive values).
Usage
{:x => 1, :y => {:z => 2}}.leaves == [1,2]
Code
class Hash # {'x'=>{'y'=>{'z'=>1,'a'=>2}}}.leaves == [1,2] def leaves leaves = [] each_value do |value| value.is_a?(Hash) ? value.leaves.each{|l| leaves << l } : leaves << value end leaves end end
I have several remarks regarding the code.
1. The commented out line has a typo (there are 3 opening braces and only 2 closing).
2. It’s better to use “leaves” instead of “leafs”.
3. `each do |key,value|` block don’t use `key` at all. Replace it with `each_value do |value|`
4. `value.respond_to?(:leaves)` looks more natural and idiomatic than `value.is_a?(Hash)`.
5. The whole method actually is an incarnation of `Enumerable#flat_map`. So it would be much shorter to rewrite it. See my final version:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
leaves.rb
hosted with ❤ by GitHub
1: duh
2: we had leaves at the start and someone said “lets look into the dictionary…” but google confirms leaves is the better choise 🙂
3: yep, should a bit be faster :>
4: seems about right
5: is only 1.9, so ill keep the original concat
Thanks for the help!
Implementation that retrieves leaf values from a hash of both hashes and arrays:
def leaves(collection)
leaves = []
if collection.is_a?(Hash)
collection.each_value { |l| leaves << leaves(l) }
elsif collection.is_a?(Array)
collection.each { |l| leaves << leaves(l) }
else
leaves << collection
end
leaves.flatten
end