Here is one example which takes the following steps:
- Sort each list by its ID
- Merge the second list into the first
defmodule Merge do
# Assumes the lists are sorted
def run do
products = [
%{id: 7, name: "A", count: 1},
%{id: 8, name: "B", count: 1},
%{id: 9, name: "C", count: 0}
]
price = [
%{price: "$10.00", p_id: 7},
%{price: "$14.95", p_id: 8},
%{price: "$1.00", p_id: 9},
%{price: "$29.95", p_id: 10}
]
merge_lists(products, price, &Map.merge/2)
end
def merge_lists([], _, _merger) do
[]
end
# A match so we merge the two maps and advance
# each list
def merge_lists([%{id: id} = head_a | rest_a], [%{p_id: id} = head_b | rest_b], merger) do
[merger.(head_a, head_b) | merge_lists(rest_a, rest_b, merger)]
end
# No match but there are more items in list_b we can try
def merge_lists([%{id: id_a} | _rest_a] = list_a, [%{p_id: id_b}| rest_b], merger)
when id_a > id_b do
merge_lists(list_a, rest_b, merger)
end
# No merge possible = No matching list b
def merge_lists([%{id: id_a} = head_a | _rest_a], [%{p_id: id_b} | _rest_b], _merger)
when id_a < id_b do
raise ArgumentError, "No match for #{inspect head_a}"
end
end
And running it:
iex> Merge.run
[
%{count: 1, id: 7, name: "A", p_id: 7, price: "$10.00"},
%{count: 1, id: 8, name: "B", p_id: 8, price: "$14.95"},
%{count: 0, id: 9, name: "C", p_id: 9, price: "$1.00"}
]