gpt4 book ai didi

functional-programming - Elixir Enum.map 与理解

转载 作者:行者123 更新时间:2023-12-04 08:41:05 24 4
gpt4 key购买 nike

我有一张 map ,我正在修改上面的每个元素,我很困惑哪种方法更好(更快)用 Enum.map 然后 Enum.into(% {}) 或用于理解,如

for {key, value} <- my_map, into: %{} do
{key, new_value}
end

最佳答案

原始答案

您可以使用 Benchee进行这种比较。

一个简单的 Benchee 测试将显示 Enum 对于这种情况更快。

iex(1)> m = %{a: 1, b: 2, c: 3, d: 4}
%{a: 1, b: 2, c: 3, d: 4}
iex(2)> with_enum = fn -> Enum.map(m, fn {k, v} -> {k, v * v} end) end
#Function<20.127694169/0 in :erl_eval.expr/5>
iex(3)> with_for = fn -> for {k, v} <- m, into: %{}, do: {k, v * v} end
#Function<20.127694169/0 in :erl_eval.expr/5>
iex(4)> Benchee.run(%{
...(4)> "with_enum" => fn -> with_enum.() end,
...(4)> "with_for" => fn -> with_for.() end
...(4)> })
Operating System: Linux
CPU Information: Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz
Number of Available Cores: 4
Available memory: 7.71 GB
Elixir 1.7.4
Erlang 21.0

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 14 s


Benchmarking with_enum...
Benchmarking with_for...

Name ips average deviation median 99th %
with_enum 28.27 K 35.37 μs ±16.16% 34.37 μs 55.21 μs
with_for 19.55 K 51.14 μs ±9.16% 50.08 μs 59.94 μs

Comparison:
with_enum 28.27 K
with_for 19.55 K - 1.45x slower

一般来说,for 不是 Elixir 中这些情况的最佳选择,它最适合列表理解,它可以非常快速地完成并具有易于阅读的语法。

Enum 的函数经过优化以处理这些更具迭代性的场景,就像您在其他编程语言中使用 for 构造所做的那样。


编辑

尽管我最初回答的主要目的是指向一个有助于运行此类比较的框架,以便 OP 可以自己尝试,正如另一位用户指出的那样,示例函数使用 Enum。 map 产生的结果与使用 for 的结果不同。正如他自己指出的那样,将 Enum.into 添加到 Enum.map 调用会导致有时运行时间更长的函数。所以这里有一个更新,添加了一些更多的选项,这些选项也被认为可以通过基准产生相同的结果。

iex> m = %{a: 1, b: 2, c: 3, d: 4}
%{a: 1, b: 2, c: 3, d: 4}
iex> with_enum_map_into = fn -> m |> Enum.map(fn {k, v} -> {k, v * v} end) |> Enum.into(%{}) end
#Function<...>
iex> with_enum_map_map_new = fn -> m |> Enum.map(fn {k, v} -> {k, v * v} end) |> Map.new() end
#Function<...>
iex> with_map_new = fn -> Map.new(m, fn {k, v} -> {k, v * v} end) end
#Function<...>
iex> with_reduce_map_put = fn -> Enum.reduce(m, %{}, fn {k, v}, acc -> Map.put(acc, k, v * v) end) end
#Function<...>
iex> with_reduce_map_merge = fn -> Enum.reduce(m, %{}, fn {k, v}, acc -> Map.merge(acc, %{k => v * v}) end) end
#Function<...>
iex> with_for = fn -> for {k, v} <- m, into: %{}, do: {k, v * v} end
#Function<20.127694169/0 in :erl_eval.expr/5>
iex> Benchee.run(%{
...> "with_for" => fn -> with_for.() end,
...> "with_enum_map_into" => fn -> with_enum_map_into.() end,
...> "with_enum_map_map_new" => fn -> with_enum_map_map_new.() end,
...> "with_map_new" => fn -> with_map_new.() end,
...> "with_reduce_map_put" => fn -> with_reduce_map_put.() end,
...> "with_reduce_map_merge" => fn -> with_reduce_map_merge.() end
...> })
Benchmarking with_enum_map_into...
Benchmarking with_enum_map_map_new...
Benchmarking with_for...
Benchmarking with_map_new...
Benchmarking with_reduce_map_merge...
Benchmarking with_reduce_map_put...

Name ips average deviation median 99th %
with_enum_map_map_new 96.55 K 10.36 μs ±158.95% 9.08 μs 37.43 μs
with_map_new 89.98 K 11.11 μs ±154.88% 8.94 μs 41.93 μs
with_enum_map_into 87.50 K 11.43 μs ±168.60% 9.46 μs 30.92 μs
with_reduce_map_put 84.31 K 11.86 μs ±63.69% 10.38 μs 38.56 μs
with_reduce_map_merge 84.29 K 11.86 μs ±91.14% 10.25 μs 38.49 μs
with_for 61.08 K 16.37 μs ±95.14% 14.18 μs 36.76 μs

Comparison:
with_enum_map_map_new 96.55 K
with_map_new 89.98 K - 1.07x slower +0.76 μs
with_enum_map_into 87.50 K - 1.10x slower +1.07 μs
with_reduce_map_put 84.31 K - 1.15x slower +1.50 μs
with_reduce_map_merge 84.29 K - 1.15x slower +1.51 μs
with_for 61.08 K - 1.58x slower +6.01 μs

在我的机器上运行基准测试时,这个顺序是一致的(因此你自己运行东西很重要),for 每次都排在最后并管道 Enum.map 进入 Map.new 一直是最快的,其次是仅使用带有映射函数的 Map.new。我确实坚持我原来的观点,即 Elixir 中的 for 主要用于理解,但它在语法上确实非常好。所有这些都是不错的选择,真的,它只是表明有几种方法可以实现同一件事,Elixir 通常就是这种情况,所以,有时它归结为偏好以及优化是否对你的目标至关重要正在做。

关于functional-programming - Elixir Enum.map 与理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55038704/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com