Skip to content

Instantly share code, notes, and snippets.

@ethagnawl
Last active August 29, 2015 14:07
Show Gist options
  • Save ethagnawl/dc3b2c5e64d9270928bc to your computer and use it in GitHub Desktop.
Save ethagnawl/dc3b2c5e64d9270928bc to your computer and use it in GitHub Desktop.
Populate Wildcards
# if you're interested, you can follow the conversation around how to make `populate_wildcards`
# more idiomatic on /r/ruby:
# https://www.reddit.com/r/ruby/comments/2iyzab/is_there_a_more_idiomatic_andor_functional_way_to/
# my initial approach
def populate_wildcards(a,b)
a.merge(b) { |key, left, right|
if left.is_a? Hash
populate_wildcards(left, right)
elsif left.is_a? Array
left.zip(right).map do |_left, _right|
populate_wildcards _left, _right
end
else
if left == '*'
right
else
left
end
end
}
end
start_hash = {a: '*', c: {d: '*', f: 'g'}}
other_hash = {a: 'b', c: {d: 'e', f: 'g'}}
result = populate_wildcards(start_hash, other_hash)
result == other_hash #=> true
============================
# @joelparkerhenderson's approach
class Hash
def merge_using_wildcard(other_hash)
merge(other_hash){|key, oldval, newval|
case oldval
when Hash
oldval.merge_using_wildcard(newval)
when '*'
newval
else
oldval
end
}
end
end
start_hash = {a: '*', c: {d: '*', f: 'g'}}
other_hash = {a: 'b', c: {d: 'e', f: 'g'}}
result = start_hash.merge_using_wildcard(other_hash)
result == other_hash #=> true
============================
# @zeringus' approach
def apply_defaults givens, defaults, wildcard = '*'
givens.merge defaults do |_key, given, default|
if given.is_a? Hash
apply_defaults given, default
else
given == wildcard ? default : given
end
end
end
start_hash = {a: '*', c: {d: '*', f: 'g'}}
other_hash = {a: 'b', c: {d: 'e', f: 'g'}}
result = apply_defaults(other_hash, start_hash)
result == other_hash #=> true
============================
# @revdan's approach
class Wildcard < Struct.new(:hash, :definitions)
def compare(a = hash, b = definitions)
a.merge(b) do |_, left, right|
if left.is_a? Hash
compare(left, right)
else
left == '*' ? right : left
end
end
end
end
Wildcard.new(
{:foo=>"*", :bar=>{:baz=>"*", :buck=>"buck"}},
{:foo=>"bar", :bar=>{:baz=>"baz", :buck=>"buck"}}
).compare
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment