Skip to content

Instantly share code, notes, and snippets.

@pmarreck
Created April 20, 2012 19:52
Show Gist options
  • Save pmarreck/2431329 to your computer and use it in GitHub Desktop.
Save pmarreck/2431329 to your computer and use it in GitHub Desktop.
attempt to traverse a hash with a key array
module HashUtils
# Pass in indexes as an array of keys
# def traverse(indexes)
# k = indexes.shift
# unless k.nil?
# v=self[k]
# if v.is_a?(Hash)
# !indexes.empty? ? v.traverse(indexes) : v
# else
# indexes.empty? ? v : nil
# end
# end
# end
def traverse(indexes)
indexes.inject(self){|v, i| v[i] if v.is_a?(Hash)}
end
# Prune a hash given a hash of any depth (where values can be other hashes)
# Takes a block which accepts |k,v|
# If the block returns true, that part of the hash is kept
# Traversal is breadth-first
def prune(&block)
inject({}) do |h, (k,v)|
if block.call(k, v)
h[k] = (v.is_a?(Hash) ? v.prune(&block) : v)
end
h
end
end
end
class Hash
include HashUtils
end
########## inline tests
if __FILE__==$0
require 'test/unit'
class ReturnValueTest < Test::Unit::TestCase
def setup
@deep_hash = {a: {b: {c: Test::Unit, d: 5}}}
end
def test_traverse_valid
assert_equal 5, @deep_hash.traverse([:a, :b, :d])
end
def test_traverse_value_ends_at_hash
assert_equal({c: Test::Unit, d: 5}, @deep_hash.traverse([:a, :b]))
end
def test_traverse_keypath_invalid_returns_nil
assert_equal nil, @deep_hash.traverse([:a, :f, :g])
end
# note: the following test was failing with original implementation of traverse
def test_traverse_keypath_past_valid_endpoint_returns_nil
assert_equal nil, @deep_hash.traverse([:a, :b, :c, :d])
end
def test_prune_block_filter
assert_equal({a: {b: {d: 5}}},
@deep_hash.prune{|k,v| [Symbol, Hash, Numeric].any?{|c| v.is_a? c }})
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment