Reputation: 1374
How can I merge two arrays with the unique key
:
keyList = ["a", "b", "c", "d"]
keyValueList = [
["a", [1, 2, 3]],
["a", [4, 5, 6]],
["b", [5, "a", 3]],
["b", ["test", 4, 3]],
["c", [1, "number", 110]]
]
to get the following?
[
["a", [[1, 2, 3], [4, 5, 6]]],
["b", [[5, "a", 3], ["test", 4, 3]]],
["c", [[1, "number", 110]]]
]
Upvotes: 1
Views: 277
Reputation: 11183
Even though it does not appear in the expected result, I'd also take keyList
into account, just in case, so:
keyList
.each_with_object({}) { |k, h| h[k] = keyValueList.select { |x, y| x == k }.map(&:last) }
.to_a
#=> [["a", [[1, 2, 3], [4, 5, 6]]], ["b", [[5, "a", 3], ["test", 4, 3]]], ["c", [[1, "number", 110]]], ["d", []]]
To get rid of ["d", []]
, just append .reject{ |e| e.last.empty? }
.
Upvotes: 0
Reputation: 110675
It's not clear why the array keyList
is needed.
keyValueList.each_with_object(Hash.new {|h,k| h[k]=[]}) do |(k,arr),h|
h[k] << arr
end.to_a
#=> [["a", [[1, 2, 3], [4, 5, 6]]],
# ["b", [[5, "a", 3], ["test", 4, 3]]],
# ["c", [[1, "number", 110]]]]
h[k] << arr
could be changed to h[k] << arr if keyList.include?(k)
if needed for the desired behavior.
The above could alternatively be written as follows.
keyValueList.each_with_object({}) do |(k,arr),h|
(h[k] ||= []) << arr
end.to_a
Upvotes: 5
Reputation: 168081
keyValueList
.group_by(&:first)
.transform_values{|a| a.map(&:last)}
.to_a
# => [
# ["a", [[1, 2, 3], [4, 5, 6]]],
# ["b", [[5, "a", 3], ["test", 4, 3]]],
# ["c", [[1, "number", 110]]]
# ]
Upvotes: 4
Reputation: 121000
Use Enumerable#group_by
:
keyValueList.
map(&:flatten).
group_by(&:shift).
select { |k, _| keyList.include?(k) }.
to_a
#⇒ [["a", [[1, 2, 3], [4, 5, 6]]],
# ["b", [[5, "a", 3], ["test", 4, 3]]],
# ["c", [[1, "number", 110]]]
Upvotes: 7