【问题标题】:In Elixir, how can I traverse a list within another loop?在 Elixir 中,如何在另一个循环中遍历列表?
【发布时间】:2015-10-17 05:32:29
【问题描述】:

给定两个列表和第三个列表,其中的值映射到前两个的排列,我想创建一个包含 list1 的键、list2 的键和 list3 的值的映射。如果我在循环中,如何在某个索引处获取 list3 的值?

据我所知,使用Enum.at 不是正确的解决方案 - 它会在每次迭代时遍历整个列表。如果我尝试[head | tail] = list3,看起来我不能只为下一个循环设置list3 = tail

list1 = [1,2]
list2 = [3,4]
list3 = 'wxyz'

Enum.each(list1), fn i ->
  Enum.each(list2), fn j ->
    # Would like to just chop off the first value of list3 and 
    # pass the tail into the next iteration
  end
end

【问题讨论】:

  • 由于无论 Enum.at 如何,我的解决方案都不可行,因此我已将其删除。但是在 Elixir 中编写嵌套循环的惯用方法是使用 Comprehensions。
  • 顺便说一句,在这种情况下,您会发现很难做比 O(n) 性能更好的事情,因为 Elixir 列表实际上是一个链表。

标签: elixir


【解决方案1】:

作为一名资深的红宝石爱好者,对我来说,扔掉.each 就像呼吸一样自然。在写了一段时间的 Elixir 之后,.each 几乎成了我的代码异味——每当我反射性地使用它时,我最终都会回去删除它,因为它会导致 Elixir 代码尴尬。

正如 cmets 中提到的,“循环”的理解是惯用的:如果您不介意遍历 3 次,则可以使用以下方法:

result = for i <- list1, j <- list2, do: {i, j}
         |> Enum.zip(list3) 
         |> Enum.into(%{})

iex> result
%{{1, 3} => 119, {1, 4} => 120, {2, 3} => 121, {2, 4} => 122}

您可以选择将其编写为一个成熟的函数,特别是如果您的示例是对更复杂事物的简化。以下函数只遍历list3一次:

defmodule MapLists do
  def map_it(l1, l2, l3, acc \\ %{})
  def map_it([], _l2, _l3, acc), do: acc
  def map_it([h|t], list2, list3, acc) do
    {res1, new_list_3} = do_map_it(h, list2, list3, %{})
    new_acc = Map.merge(acc, res1)
    map_it(t, list2, new_list_3, new_acc)
  end


  defp do_map_it(item, [], l3, acc), do: {acc, l3}
  defp do_map_it(item, [h2|t2], [h3|t3], acc) do
    new_acc = Map.put(acc, {item, h2}, h3)
    do_map_it(item, t2, t3, new_acc)
  end
end

及用法:

iex> MapLists.map_it([1,2],[3,4],'wxyz')
%{{1, 3} => 119, {1, 4} => 120, {2, 3} => 121, {2, 4} => 122}

【讨论】:

  • 第二个答案正是我一直在寻找的——我最看重的是精益求精。我也从 Ruby 世界跳入 Elixir。
  • @DonPflaster 我很幸运有一位经验丰富的 erlang 程序员帮助我完成过渡...根据我的经验,我强烈建议暂时编写原始 erlang,这将教你很多关于长生不老药的知识
  • 我本能地有一种感觉,我不会找到优雅的东西来做我想做的事。我们当然不会为了优雅而使用这种语言。 :) 感谢您的出色回答。
猜你喜欢
  • 2022-01-06
  • 2018-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-01
相关资源
最近更新 更多