2017-04-13 33 views

回答

3

使用Map.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] 
+0

好的。如果我只是有一个键和一张地图的列表,我想检查哪些键不存在于地图中,我该怎么做? – Otoma

+0

你可以使用['Map.has_key?'](https://hexdocs.pm/elixir/Map.html#has_key?/2)或类似的东西:'keys - Map.keys(map)' – Sheharyar

+0

什么是'--'? – Otoma

3

--是大型列表极其低效。由于您已经拥有地图,因此您可以使用Map.has_key?/2查找O(log n)时间内任意键的存在。一个简单的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] 

快速基准与大地图显示了巨大的性能差异VS 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 

如果你的地图虽然很小,但是--肯定比这个短一些,可读性也应该足够好。

相关问题