projects_with_roles = [
{ id: 1, name: 'First', roles: ['user', 'compliance_lead'] },
{ id: 5, name: 'Five', roles: ['financial_lead'] }
]
projects_to_add = [
{ id: 5, name: 'Five', roles: ['technical_lead'] },
{ id: 10, name: 'Ten', roles: ['user'] }
]
(projects_with_roles + projects_to_add).each_with_object({}) do |g,h|
h.update([g[:id], g[:name]]=>g[:roles]) { |_,o,n| o|n }
end.map { |(id,name),roles| { id: id, name: name, roles:roles } }
#=> [{:id=>1, :name=>"First", :roles=>["user", "compliance_lead"]},
# {:id=>5, :name=>"Five", :roles=>["financial_lead", "technical_lead"]},
# {:id=>10, :name=>"Ten", :roles=>["user"]}]
Это не изменяет projects_with_roles
. Если это желательно, установите projects_with_roles
равным вышеуказанному вычислению.
Здесь используется форма Hash # update (также известная как merge!
), которая использует блок { |_,o,n| o|n }
для определения значения ключей, которые присутствуют в обоих сливаемых хэшах. См. Do c для объяснения значений трех переменных блока (_
, o
и n
). (Я представил первый общий ключ с подчеркиванием, чтобы указать, что он не используется в вычислении блока.
Обратите внимание, что промежуточное вычисление выглядит следующим образом:
(projects_with_roles + projects_to_add).each_with_object({}) do |g,h|
h.update([g[:id], g[:name]]=>g[:roles]) { |_,o,n| o|n }
end
#=> {[1, "First"]=>["user", "compliance_lead"],
# [5, "Five"]=>["financial_lead", "technical_lead"],
# [10, "Ten"]=>["user"]}
Путем построения ha sh и последующего преобразования его в массив хэшей вычислительная сложность сохраняется почти на уровне O(projects_with_roles.size + projects_to_add.size)
, поскольку поиск ключей ha sh близок к O(1)
.