我想知道如何用递归对这个散列数组中的“解析”值求和。
输入:
[{"id"=>"1234",
"id_data"=>
[{"segment"=>{"segment_name"=>"Android"},
"metrics"=>
{
"logins"=>[1000, 2000],
"sign_ups_conversion"=>{
"count"=>[500, 200],
"cost"=>[2, 4]
}
},
},
{"segment"=>{"segment_name"=>"iOS"},
"metrics"=>
{
"logins"=>[5000, 10000],
"sign_ups_conversion"=>{
"count"=>[100, 50],
"cost"=>[6, 8]
}
},
}
]
},
{"id"=>"5678",
"id_data"=>
[{"segment"=>{"segment_name"=>"Android"},
"metrics"=>
{
"logins"=>[3000, 2000],
"sign_ups_conversion"=>{
"count"=>[300, 400],
"cost"=>[2, 4]
}
},
},
{"segment"=>{"segment_name"=>"iOS"},
"metrics"=>
{
"logins"=>[5000, 10000],
"sign_ups_conversion"=>{
"count"=>[100, 50],
"cost"=>[6, 8]
}
},
}
]
}]
输出
{
"Android"=>{
"ids" => ['1234','5678'],
"segment" => {"segment_name"=>"Android"},
"id_data" => [{
"logins" => [4000, 4000], # sum by index from 'Android' logins ("logins"=>[1000, 2000] & "logins"=>[3000, 2000]),
"sign_ups_conversion" => {
"count" => [800, 600], # sum by index from 'Android' sign ups count ("count"=>[500, 200] & "count"=>[300, 400])
"cost" => [4, 8] # sum by index from 'Android' sign ups cost ("cost"=>[2, 4] & "cost"=>[2, 4])
}
}]
},
"iOS"=>{
"ids" => ['1234','5678'],
"segment" => {"segment_name"=>"iOS"},
"id_data" => [{
"logins" => [10000, 20000], # sum by index from 'iOS' logins ("logins"=>[5000, 10000] & "logins"=>[5000, 10000]),
"sign_ups_conversion" => {
"count" => [200, 100], # sum by index from 'iOS' sign ups count ("count"=>[100, 50] & "count"=>[100, 50])
"cost" => [12, 16] # sum by index from 'iOS' sign ups cost ("cost"=>[6, 8] & "cost"=>[6, 8])
}
}]
}
}
我,试图用这种方法解决它,但它没有用哈希格式(sign_ups_conversion
)计算分析,并且仍在计算结果应该如何等于输出。
def aggregate_by_segments(stats_array)
results = {}
stats_array.each do |stats|
stats['id_data'].each do |data|
segment_name = data['segment']['segment_name']
results[segment_name] ||= {}
(results[segment_name]['ids'] ||= []) << stats['id']
results[segment_name]['segment'] ||= data['segment']
results[segment_name]['id_data'] ||= [{}]
data['metrics'].each do |metric, values|
next if skip_metric?(values)
(results[segment_name]['id_data'][0][metric] ||= []) << values
end
end
end
sum_segments(results)
end
def sum_segments(segments)
segments.each do |segment, segment_details|
segment_details['id_data'][0].each do |metric, values|
segment_details['id_data'][0][metric] = sum_segment_metric(values)
end
end
segments
end
def sum_segment_metric(metric_value)
metric_value.transpose.map { |x| x.reduce(:+) }
end
# I skipped hash format for now
def skip_metric?(metric_values)
!metric_values.is_a? Array
end
############################################
# calls it with aggregate_by_segments(input)
############################################
我相信我们应该使用递归,但我还在想,任何人都可以帮助我吗?
提前致谢!
答案 0 :(得分:0)
这里的问题是如何访问这些数据结构,一个ruby策略可以使用每个数据迭代数组,并使用这样的连接哈希来连接键:
假设你的结构被保留:
<强>数组[散列[阵列[散列]] 强>
array_hash.each do |stats|
stats["id_data"].each do |h|
puts h["metrics"]["sign_ups_conversion"]
end
end
# => {"count"=>[500, 200], "cost"=>[2, 4]}
# => {"count"=>[100, 50], "cost"=>[6, 8]}
# => {"count"=>[300, 400], "cost"=>[2, 4]}
# => {"count"=>[100, 50], "cost"=>[6, 8]}
答案 1 :(得分:0)
我解决了。
def aggregate_by_segments(stats_array)
results = {}
stats_array.each do |stats|
stats['id_data'].each do |data|
segment_name = data['segment']['segment_name']
results[segment_name] ||= {}
(results[segment_name]['ids'] ||= []) << stats['id']
results[segment_name]['segment'] ||= data['segment']
results[segment_name]['id_data'] ||= [{}]
data['metrics'].each do |metric, values|
hash_values(results[segment_name]['id_data'][0], metric, values) if values.is_a? Hash
next if skip_metric?(values)
(results[segment_name]['id_data'][0][metric] ||= []) << values
end
end
end
sum_segments(results)
end
def hash_values(metrics, metric, hash_values)
hash_values.each do |k, v|
next if skip_metric?(v)
metrics[metric] ||= {}
(metrics[metric][k] ||= []) << v
end
end
def sum_segments(segments)
segments.each do |segment, segment_details|
segment_details['id_data'][0].each do |metric, values|
segment_details['id_data'][0][metric] = sum_segment_metric(values)
end
end
segments
end
def sum_segment_metric(metric_value)
result = metric_value.transpose.map { |x| x.reduce(:+) } if metric_value.is_a? Array
result = metric_value.each do |k, v|
metric_value[k] = sum_segment_metric(v)
end if metric_value.is_a? Hash
result
end
def skip_metric?(metric_values)
!metric_values.is_a? Array
end
我知道代码非常难看。我稍后会重构它:)
感谢各位访问和评论建设性反馈。