给定两个列表和第三个列表,其值具有映射到前两个列表的排列,我想创建一个list1的key,list2的键和list3的值的Map。如果我在循环中,如何在某个索引处获取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
答案 0 :(得分:3)
作为一个长期的红宝石,放下.each
变得和我呼吸一样自然。在写了Elixir一段时间之后,.each
几乎成了我的代码气味 - 每当我通过反射使用它时,我最终会回去删除它,因为它会导致笨拙的Elixir代码。
正如评论中所提到的那样,理解是循环的#34;如果你不介意遍历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}