Elixir获取每个列表中唯一的元素

时间:2017-05-22 20:47:38

标签: elixir

我有两个清单 1 = [%{name: "hi"}, %{name: "hu"}] 2 = [%{name: "hi"}, %{name: "ha"}]

现在我希望有2个列表只包含每个列表1和2中唯一的元素 1_uniq = [%{name: "hu"}] 2_uniq = [%{name: "ha"}]

我怎么能实现这个目标?

2 个答案:

答案 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)))