我有两个清单
1 = [%{name: "hi"}, %{name: "hu"}]
2 = [%{name: "hi"}, %{name: "ha"}]
现在我希望有2个列表只包含每个列表1和2中唯一的元素
1_uniq = [%{name: "hu"}]
2_uniq = [%{name: "ha"}]
我怎么能实现这个目标?
答案 0 :(得分:2)
您可以为这两个列表创建一个名称列表集,将它们相交以查找常用名称,然后过滤掉所有常用名称。以下是使用Elixir中的MapSet
模块执行此操作的方法:
l1 = [%{name: "hi"}, %{name: "hu"}]
l2 = [%{name: "hi"}, %{name: "ha"}]
# set of names
s1 = for x <- l1, into: MapSet.new, do: x.name
s2 = for x <- l2, into: MapSet.new, do: x.name
# set of common names
common = MapSet.intersection(s1, s2)
# filter out any name that's in `common`
l1_unique = for x <- l1, !MapSet.member?(common, x.name), do: x
l2_unique = for x <- l2, !MapSet.member?(common, x.name), do: x
IO.inspect l1_unique
IO.inspect l2_unique
输出:
[%{name: "hu"}]
[%{name: "ha"}]
答案 1 :(得分:1)
使用与@Dogbert相同的想法,我更喜欢以下代码段,因为您执行的迭代更少,
l1 = [%{name: "hi"}, %{name: "hu"}]
l2 = [%{name: "hi"}, %{name: "ha"}]
set = MapSet.new(l1 ++ l2)
l1_uniq = Enum.reject(set, &(Enum.member?(l2, &1)))
l2_uniq = Enum.reject(set, &(Enum.member?(l1, &1)))
您可以在不使用MapSet
的情况下实现相同的解决方案:
l1 = [%{name: "hi"}, %{name: "hu"}]
l2 = [%{name: "hi"}, %{name: "ha"}]
set = Enum.uniq(l1 ++ l2)
l1_uniq = Enum.reject(set, &(Enum.member?(l2, &1)))
l2_uniq = Enum.reject(set, &(Enum.member?(l1, &1)))