在 ruby 中实施合并方法
Implement merge method in ruby
我正在尝试在我的代码中实现合并方法。
A = { "a" => 200, "b" => 100 }
B = { "b" => 100, "c" => 300 }
所以当我在主函数中调用 A.merge_method(B)
时,它应该 return
A.merge_method(B) #=> {"a"=>200, "b"=>200, "c"=>300}
不使用合并方法如何实现?
总体思路是:收集要合并的任何哈希的所有键,然后对于每个键,收集具有该键的所有哈希中的值,并将它们相加。
module HashWithMergeReduce
refine Hash do
def merge_reduce(*others, &op)
hashes = [self, *others]
hash_keys = hashes.map(&:keys).inject(Set.new, &:+)
hash_keys.each do |key|
hashes_with_key = hashes.select { |hash| hash.has_key?(key) }
self[key] = hashes_with_key.map { |hash| hash[key] }.reduce(&op)
end
self
end
end
end
module TestHashWithMergeReduce
using HashWithMergeReduce
a = { "a" => 200, "b" => 100 }
b = { "b" => 100, "c" => 300 }
puts a.merge_reduce(b, &:+)
# => {"a"=>200, "b"=>200, "c"=>300}
end
我不能把方法merge_method
添加到class Hash
,不仅因为它污染了核心class,而且因为它是仅适用于一小部分散列,所有值都是数字的散列。
有人可以 refine
Hash
,就像@Amadan 所做的那样,但我认为简单地创建一个类似于模块方法的方法更有意义,该方法的行为类似于函数(例如,Math::sqrt
),它将所有哈希值作为参数。
def sum_values_by_key(*hashes)
hashes.each_with_object(Hash.new(0)) { |g,h| g.each { |k,v| h[k] += v } }
end
sum_values_by_key({ "a" => 200, "b" => 100 }, { "b" => 100, "c" => 300 })
#=> {"a"=>200, "b"=>200, "c"=>300}
sum_values_by_key({ "a" => 200, "b" => 100 }, { "b" => 100, "c" => 300 },
{ "a" => 150, "c" => 250 })
#=> {"a"=>350, "b"=>200, "c"=>550}
这使用定义默认值的 Hash::new 形式,此处为零。表达式:
h[k] += v
扩展为:
h[k] = h[k] + v
如果这个散列已经被定义h = Hash.new(0)
并且h
有一个键k
,h[k]
右边的等式被计算为return k
的值。但是,如果 h
没有键 k
,h[k]
右边的 returns 默认值,零,变为:
h[k] = 0 + v
我还更改了方法名称以使其更有意义。
我正在尝试在我的代码中实现合并方法。
A = { "a" => 200, "b" => 100 }
B = { "b" => 100, "c" => 300 }
所以当我在主函数中调用 A.merge_method(B)
时,它应该 return
A.merge_method(B) #=> {"a"=>200, "b"=>200, "c"=>300}
不使用合并方法如何实现?
总体思路是:收集要合并的任何哈希的所有键,然后对于每个键,收集具有该键的所有哈希中的值,并将它们相加。
module HashWithMergeReduce
refine Hash do
def merge_reduce(*others, &op)
hashes = [self, *others]
hash_keys = hashes.map(&:keys).inject(Set.new, &:+)
hash_keys.each do |key|
hashes_with_key = hashes.select { |hash| hash.has_key?(key) }
self[key] = hashes_with_key.map { |hash| hash[key] }.reduce(&op)
end
self
end
end
end
module TestHashWithMergeReduce
using HashWithMergeReduce
a = { "a" => 200, "b" => 100 }
b = { "b" => 100, "c" => 300 }
puts a.merge_reduce(b, &:+)
# => {"a"=>200, "b"=>200, "c"=>300}
end
我不能把方法merge_method
添加到class Hash
,不仅因为它污染了核心class,而且因为它是仅适用于一小部分散列,所有值都是数字的散列。
有人可以 refine
Hash
,就像@Amadan 所做的那样,但我认为简单地创建一个类似于模块方法的方法更有意义,该方法的行为类似于函数(例如,Math::sqrt
),它将所有哈希值作为参数。
def sum_values_by_key(*hashes)
hashes.each_with_object(Hash.new(0)) { |g,h| g.each { |k,v| h[k] += v } }
end
sum_values_by_key({ "a" => 200, "b" => 100 }, { "b" => 100, "c" => 300 })
#=> {"a"=>200, "b"=>200, "c"=>300}
sum_values_by_key({ "a" => 200, "b" => 100 }, { "b" => 100, "c" => 300 },
{ "a" => 150, "c" => 250 })
#=> {"a"=>350, "b"=>200, "c"=>550}
这使用定义默认值的 Hash::new 形式,此处为零。表达式:
h[k] += v
扩展为:
h[k] = h[k] + v
如果这个散列已经被定义h = Hash.new(0)
并且h
有一个键k
,h[k]
右边的等式被计算为return k
的值。但是,如果 h
没有键 k
,h[k]
右边的 returns 默认值,零,变为:
h[k] = 0 + v
我还更改了方法名称以使其更有意义。