如何合并两个对象并保持计数
How to merge two objects and keep count
我正在构建一个 Rails 5.2 应用程序。
在这个应用程序中,我正在处理统计数据。
我生成了两个对象:
{
"total_project": {
"website": 1,
"google": 1,
"instagram": 1
}
}
还有这个:
{
"total_leads": {
"website": 1,
"google": 2,
"client_referral": 1
}
}
我需要将这两个对象合并为一个对象以增加计数。期望的结果是:
{
"total_both": {
"website": 2,
"google": 3,
"instagram": 1,
"client_referral": 1
}
}
我试过了,技术上可行,它合并了对象,但计数没有更新:
@total_project = array_projects.group_by { |d| d[:entity_type] }.transform_values(&:count).symbolize_keys
@total_leads = array_leads.group_by { |d| d[:entity_type] }.transform_values(&:count).symbolize_keys
@total_sources = merged.merge **@total_project, **@total_leads
请注意,属性(来源)是数据库中的动态属性,因此我无法对任何内容进行硬编码。用户可以添加自己的来源。
@total_sources = @total_project.merge(@total_leads) do |key, ts_value, tp_value|
ts_value + tp_value
end
如果源可以超过 2 个,则将所有内容放入一个数组中并执行。
@total_sources = source_array.reduce do |accumulator, next_source|
accumulator.merge(next_source) { |key, v1, v2| v1 + v2 }
end
您可以按如下方式计算所需的结果。
arr = [{ "total_project": { "website": 1, "google": 1, "instagram": 1 } },
{ "total_leads": { "website": 1, "google": 2, "client_referral": 1 } }]
{ "total_both" => arr.flat_map(&:values)
.reduce { |h,g| h.merge(g) { |_,o,n| o+n } } }
#=> {"total_both"=>{:website=>2, :google=>3, :instagram=>1, :client_referral=>1}}
注意
arr.flat_map(&:values)
#=> [{:website=>1, :google=>1, :instagram=>1},
# {:website=>1, :google=>2, :client_referral=>1}]
如果我使用 Array#map 这会是
arr.map(&:values)
#=> [[{:website=>1, :google=>1, :instagram=>1}],
# [{:website=>1, :google=>2, :client_referral=>1}]]
请参阅 Enumerable#flat_map, Enumerable#reduce and the form of Hash#merge,它采用一个块(此处为 { |_,o,n| o+n }
),其中 returns 合并两个散列中存在的键的值。请参阅 merge
的文档以了解三个块变量的定义(此处为 _
、o
和 n
)。我已将第一个块变量(持有公共键)命名为 _
以向 reader 发出信号,表明它未在块计算中使用(常见的 Ruby 约定)。
我正在构建一个 Rails 5.2 应用程序。 在这个应用程序中,我正在处理统计数据。
我生成了两个对象:
{
"total_project": {
"website": 1,
"google": 1,
"instagram": 1
}
}
还有这个:
{
"total_leads": {
"website": 1,
"google": 2,
"client_referral": 1
}
}
我需要将这两个对象合并为一个对象以增加计数。期望的结果是:
{
"total_both": {
"website": 2,
"google": 3,
"instagram": 1,
"client_referral": 1
}
}
我试过了,技术上可行,它合并了对象,但计数没有更新:
@total_project = array_projects.group_by { |d| d[:entity_type] }.transform_values(&:count).symbolize_keys
@total_leads = array_leads.group_by { |d| d[:entity_type] }.transform_values(&:count).symbolize_keys
@total_sources = merged.merge **@total_project, **@total_leads
请注意,属性(来源)是数据库中的动态属性,因此我无法对任何内容进行硬编码。用户可以添加自己的来源。
@total_sources = @total_project.merge(@total_leads) do |key, ts_value, tp_value|
ts_value + tp_value
end
如果源可以超过 2 个,则将所有内容放入一个数组中并执行。
@total_sources = source_array.reduce do |accumulator, next_source|
accumulator.merge(next_source) { |key, v1, v2| v1 + v2 }
end
您可以按如下方式计算所需的结果。
arr = [{ "total_project": { "website": 1, "google": 1, "instagram": 1 } },
{ "total_leads": { "website": 1, "google": 2, "client_referral": 1 } }]
{ "total_both" => arr.flat_map(&:values)
.reduce { |h,g| h.merge(g) { |_,o,n| o+n } } }
#=> {"total_both"=>{:website=>2, :google=>3, :instagram=>1, :client_referral=>1}}
注意
arr.flat_map(&:values)
#=> [{:website=>1, :google=>1, :instagram=>1},
# {:website=>1, :google=>2, :client_referral=>1}]
如果我使用 Array#map 这会是
arr.map(&:values)
#=> [[{:website=>1, :google=>1, :instagram=>1}],
# [{:website=>1, :google=>2, :client_referral=>1}]]
请参阅 Enumerable#flat_map, Enumerable#reduce and the form of Hash#merge,它采用一个块(此处为 { |_,o,n| o+n }
),其中 returns 合并两个散列中存在的键的值。请参阅 merge
的文档以了解三个块变量的定义(此处为 _
、o
和 n
)。我已将第一个块变量(持有公共键)命名为 _
以向 reader 发出信号,表明它未在块计算中使用(常见的 Ruby 约定)。