【问题标题】:Which way to compare maps in Elixir在 Elixir 中比较地图的方法
【发布时间】:2025-11-30 15:15:02
【问题描述】:

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

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

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

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

==/2Map.equal?/2出现这个时间差的原因是什么,用哪个?

等效地,在==/2===/2 之间使用哪个? (因为Map.equal?/2调用===/2,见here

谢谢

【问题讨论】:

    标签: erlang elixir


    【解决方案1】:

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

    Kernel.===/2 委派给 :erlang."=:="/2Kernel.==/2 委派给 :erlang."=="/2。后者比较数字,而前者比较values and types

    考虑以下示例。

    %{1 => 1} == %{1 => 1.0}
    #⇒ true
    
    %{1 => 1} === %{1 => 1.0}
    #⇒ false
    

    也就是说,Kernel.===/2 应该比较所有值。 OTOH,Erlang/OTP 参考 explicitly states

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

    如果确实如此,那么两个不同大小的地图(如您的示例中所示)应该几乎同时返回。


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

    【讨论】:

    • 这已被报告。感谢您对这个主题的深入了解。
    • 备案:固定在此pull request
    最近更新 更多