Reputation: 4634
I got two array which seems similar, part of them are duplicate, and I need to combine them.
Here is the first array.
first
[
{
:group_id => "12873",
:question_sets => [
{
:id => 29435,
:name => "Question1"
},
{
:id => 29349,
:name => "Question2"
},
]
},
{
:group_id => "12876",
:question_sets => [
{
:id => 29443,
:name => "Question3"
}
]
}
]
Here is second array
[
{
:group_id => "12873",
:question_sets => [
{
:id => 29435,
:name => "Question1"
},
{
:id => 29338,
:name => "Question4"
},
]
},
{
:group_id => "12888", #(not in first array)
:question_sets => [
{
:id => 29443,
:name => "Question3"
}
]
}
]
The idea was to combine the question_sets's id
and name
by the same group_id
, every record in second array need to be combined. If there is no the same group_id
, create the group_id
.
The result will be like
[
{
:group_id => "12873",
:question_sets => [
{
:id => 29435,
:name => "Question1"
},
{
:id => 29349,
:name => "Question2"
},
{
:id => 29338,
:name => "Question4"
}
]
},
{
:group_id => "12876",
:question_sets => [
{
:id => 29443,
:name => "Question3"
}
]
},
{
:group_id => "12888",
:question_sets => [
{
:id => 29443,
:name => "Question3"
}
]
}
]
Upvotes: 0
Views: 85
Reputation: 110645
If h1
and h2
are hashes with keys :id
and :name
, I've assumed that h1[:name] == h2[:name]
if and only if h1[:id] == h2[:id]
If a1
and a2
equal your two arrays, you could do the following.
(a1+a2).group_by { |h| h[:group_id] }.
map { |k,v| { group_id: k,
question_sets: v.flat_map { |g| g[:question_sets] }.uniq } }
#=> [{:group_id=>"12873",
# :question_sets=>[
# {:id=>29435, :name=>"Question1"},
# {:id=>29349, :name=>"Question2"},
# {:id=>29338, :name=>"Question4"}
# ]
# },
# {:group_id=>"12876",
# :question_sets=>[{:id=>29443, :name=>"Question3"}]
# },
# {:group_id=>"12888",
# :question_sets=>[{:id=>29443, :name=>"Question3"}]
# }
# ]
The steps are as follows.
a = a1+a2
#=> [{:group_id=>"12873",
# :question_sets=>[
# {:id=>29435, :name=>"Question1"},
# {:id=>29349, :name=>"Question2"}
# ]
# },
# {:group_id=>"12876",
# :question_sets=>[{:id=>29443, :name=>"Question3"}]
# },
# {:group_id=>"12873",
# :question_sets=>[
# {:id=>29435, :name=>"Question1"},
# {:id=>29338, :name=>"Question4"}
# ]
# },
# {:group_id=>"12888",
# :question_sets=>[{:id=>29443, :name=>"Question3"}]
# }
# ]
b = a.group_by { |h| h[:group_id] }
#=> {"12873"=>[
# {:group_id=>"12873",
# :question_sets=>[
# {:id=>29435, :name=>"Question1"},
# {:id=>29349, :name=>"Question2"}
# ]
# },
# {:group_id=>"12873",
# :question_sets=>[
# {:id=>29435, :name=>"Question1"},
# {:id=>29338, :name=>"Question4"}
# ]
# }
# ],
# "12876"=>[
# {:group_id=>"12876",
# :question_sets=>[{:id=>29443, :name=>"Question3"}]
# }
# ],
# "12888"=>[
# {:group_id=>"12888",
# :question_sets=>[{:id=>29443, :name=>"Question3"}]
# }
# ]
# }
b.map { |k,v| { group_id: k,
question_sets: v.flat_map { |g| g[:question_sets] }.uniq } }
#=> array of hashes shown above.
Consider the first element of b
passed to map
's block, to which the block variables are assigned:
k,v = b.first
k #=> "12873",
v #=> [{:group_id=>"12873",
# :question_sets=>[
# {:id=>29435, :name=>"Question1"},
# {:id=>29349, :name=>"Question2"}
# ]
# },
# {:group_id=>"12873",
# :question_sets=>[
# {:id=>29435, :name=>"Question1"},
# {:id=>29338, :name=>"Question4"}
# ]
# }
# ]
so the block calculation, which constructs a hash, is as follows.
c = v.flat_map { |g| g[:question_sets] }
#=> [{:id=>29435, :name=>"Question1"},
# {:id=>29349, :name=>"Question2"},
# {:id=>29435, :name=>"Question1"},
# {:id=>29338, :name=>"Question4"}]
d = c.uniq
#=> [{:id=>29435, :name=>"Question1"},
# {:id=>29349, :name=>"Question2"},
# {:id=>29338, :name=>"Question4"}]
so the block returns the hash
{ group_id: k, question_sets: d }
#=> { group_id: "12873",
# question_sets: [
# {:id=>29435, :name=>"Question1"},
# {:id=>29349, :name=>"Question2"},
# {:id=>29338, :name=>"Question4"}
# ]
# }
The remaining calculations are similar.
Upvotes: 1