假设您有一个散列,其中键是字符串,值是Floats。您希望按每个键的子字符串对值进行分组,然后对每个组中的值求和。
基本上,你想要离开这个:
{ "aaaapattern1aaaa" => 213.2342, "pattern2aaaa" => 0.03,
"aaaaapattern3" => 12.1, "pattern1aaa" => 54.4544,
"aaaaapattern2" => 65.003 }
到此:
{"pattern1"=>267.6886, "pattern2"=>65.033, "pattern3"=>12.1}
这是我目前的做法:
data = {
"aaaapattern1aaaa"=>213.2342, "pattern2aaaa"=>0.03,
"aaaaapattern3"=>12.1, "pattern1aaa"=>54.4544,
"aaaaapattern2"=>65.003
}
key_regexp = /pattern\d/
intermediate_results = data.map do |key, value|
{ key.match(key_regexp)[0] => value }
end
final_result = intermediate_results.reduce do |cumulative_hash, individual_hash|
cumulative_hash.merge(individual_hash) do |key, old_value, new_value|
old_value + new_value
end
end
你会如何改进?在制定理想方法时应考虑哪些因素?你的答案是否会根据哈希的大小而改变,如果是的话,怎么样?
答案 0 :(得分:3)
这应该是非常简单的很多工作:
sums = Hash.new(0)
d.each do |key, value|
if (m = key.match(/pattern\d/))
sums[m[0]] += value
end
end
sums
# => {"pattern1"=>267.6886, "pattern2"=>65.033, "pattern3"=>12.1}
这有利于忽略任何不匹配的东西。
此处Hash.new(0)
创建一个默认值为0
的哈希值。这是一个很好的模式,用于组合任意事物的总和。
答案 1 :(得分:0)
我想我会做类似下面的事情。我不能过多地谈论表现。
sums = Hash.new(0) #Initialize hash with 0 as default
data.each do |k,v|
case k #switch on the key
when /pattern1/ #do regex pattern checks
sums[:pattern_1] += v
when /pattern2/
sums[:pattern_2] += v
else
#undefined pattern
end
end
答案 2 :(得分:0)
如果你使用each_with_object,你可以使它相当紧凑。
假设data
和key_regexp
与您定义的相同:
data.each_with_object(Hash.new(0)) do |(k,v),r|
r[k.match(key_regexp)[0]] += v
end