在 Elixir 中比较地图的方法

mlj*_*jrg 5 erlang elixir

给定两个不同的大地图,定义如下

Interactive Elixir (1.9.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> m1 = Map.new(1..1_000_000 |> Enum.map(&{&1, &1})); :ok
:ok
iex(2)> m2 = Map.new(2..1_000_000 |> Enum.map(&{&1, &1})); :ok
:ok
Run Code Online (Sandbox Code Playgroud)

使用==/2和比较它们时需要显着的时间差异Map.equal?/2

iex(3)> :timer.tc(fn -> m1 == m2 end)
{21, false}
iex(4)> :timer.tc(fn -> Map.equal?(m1, m2) end)
{20487, false}
Run Code Online (Sandbox Code Playgroud)

==/2和之间的时间差异是什么原因,Map.equal?/2使用哪个?

同样,在==/2和之间使用哪个===/2?(因为Map.equal?/2调用===/2,请参见此处

谢谢

Ale*_*kin 9

事实上,Map.equal?/2只是委托给Kernel.===/2

Kernel.===/2正在委托给:erlang."=:="/2并且Kernel.==/2正在委托给:erlang."=="/2。后者比较数字,而前者比较值和类型

考虑以下示例。

%{1 => 1} == %{1 => 1.0}
#? true

%{1 => 1} === %{1 => 1.0}
#? false
Run Code Online (Sandbox Code Playgroud)

也就是说,Kernel.===/2应该比较所有值。OTOH,二郎山/ OTP参考明确指出的是

映射按大小排序,大小相同的两个映射按关键字升序进行比较,然后按关键字顺​​序按值进行比较。在地图中,键顺序整数类型被认为小于浮点类型。

如果确实如此,则如您的示例中所示,大小不同的两张地图应该几乎同时返回。


综上所述,我认为这个时间差是实现中的一个错误:erlang."=:="/2,值得向Erlang团队报告。

  • 这已被报道。感谢您对这个主题的深入了解。 (2认同)
  • 郑重声明:**已在此 [拉取请求](https://github.com/erlang/otp/pull/2526) 中修复**。 (2认同)