查找存在于一个地图中但不存在于另一个地图中的关键字

时间:2017-04-13 02:58:02

标签: elixir

我有2张地图。有什么方法可以找出一个Map中存在哪些密钥,但另一个密钥中不存在这些密钥?

2 个答案:

答案 0 :(得分:3)

documentationMap.keys/1一起使用是最简单的方法:

# Suppose your two maps are:
map_a = %{a: 1, b: 2, c: 3, d: 4}
map_b = %{c: 3, d: 4, e: 5, f: 6}


# Get keys present in map_a but not in map_b
a_b_diff = Map.keys(map_a) -- Map.keys(map_b)        # => [:a, :b]


# Get keys present in map_b but not in map_a
b_a_diff = Map.keys(map_b) -- Map.keys(map_a)        # => [:e, :f]

答案 1 :(得分:3)

对于大型列表,

--效率非常低。由于您已有地图,因此您可以使用O(log n)Map.has_key?/2时间内查找是否存在任何密钥。可以使用带过滤器的简单for来获得所需的结果:

iex(1)> map1 = %{a: 1, b: 2, d: 3, f: 4}
%{a: 1, b: 2, d: 3, f: 4}
iex(2)> map2 = %{b: 5, c: 6, f: 7, g: 8}
%{b: 5, c: 6, f: 7, g: 8}
iex(3)> for {k, _} <- map1, !Map.has_key?(map2, k), do: k
[:a, :d]

使用大型地图的快速基准测试显示与Kernel.--/2的巨大性能差异:

map1 = for x <- Enum.take_random(1..10000, 5000), into: %{}, do: {x, x}
map2 = for x <- Enum.take_random(1..10000, 5000), into: %{}, do: {x, x}

{time, result1} = :timer.tc(fn ->
  Map.keys(map1) -- Map.keys(map2)
end)
IO.puts "--: #{time}µs"

{time, result2} = :timer.tc(fn ->
  for {k, _} <- map1, !Map.has_key?(map2, k), do: k
end)
IO.puts "for: #{time}µs"

IO.inspect result1 == result2

输出:

--: 113367µs
for: 739µs
true

如果您的地图很小,--肯定会比这更短,更可读,并且应该足够好。