【发布时间】:2019-11-13 10:49:43
【问题描述】:
我不明白如何在 Elixir 中使用索引进行迭代。
比如我有这个来自java的sn-p,我想把它翻译成Elixir:
for(int i = 1; i < list.size(); i++) {
list.order = i;
}
假设list 是来自 Elixir 的地图列表。
我无法理解如何以 Elixir 方式执行此操作,或者只是使用一些索引变量进行迭代。
【问题讨论】:
标签: elixir
我不明白如何在 Elixir 中使用索引进行迭代。
比如我有这个来自java的sn-p,我想把它翻译成Elixir:
for(int i = 1; i < list.size(); i++) {
list.order = i;
}
假设list 是来自 Elixir 的地图列表。
我无法理解如何以 Elixir 方式执行此操作,或者只是使用一些索引变量进行迭代。
【问题讨论】:
标签: elixir
虽然贾斯汀的回答完全有效,但惯用的 Elixir 解决方案是使用 Enum.with_index/2:
list = ~w|a b c d e|
list
|> Enum.with_index()
|> Enum.each(fn {e, idx} -> IO.puts "Elem: #{e}, Idx: #{idx}" end)
#⇒ Elem: a, Idx: 0
#⇒ Elem: b, Idx: 1
#⇒ Elem: c, Idx: 2
#⇒ Elem: d, Idx: 3
#⇒ Elem: e, Idx: 4
【讨论】:
Enum.with_index 是否允许更新 Map 上的值(这是我认为 OP 想要的,而不仅仅是一种简单迭代的方法)?
Enum.with_index 不 allow 或 disallow 任何东西,它传递元素,附加一个索引并返回一个元组。如果输入是要更新的map,则应在最后一行管道中使用Enum.map 或Enum.reduce 而不是Enum.each。 Elixir 中没有这样的“地图更新”。结果仍然是新地图。
Repo.all(query) |> Enum.with_index(1) |> Enum.each(fn {l, idx} -> update_lesson(l, %{order: idx}) end)update_lesson 只是带有变更集的 Repo.update()。
使用不允许数据变异的语言时,它不像迭代集合和设置值那么简单。相反,您需要使用已设置字段的新对象创建一个新集合。
在 Elixir 中,您可以使用 foldl:
List.foldl(
list,
(1, map),
fn(l, (i, map)) -> (i+1, Map.update(map, :some_key, $(i)))
)
【讨论】:
或者使用for理解
[debug] localized_titles %{attributes: [%{"en" => "The English Title of a Playlist"}, %{"fr" => "Le French Title of a Playlist"}]}
maps =
for title <- localized_titles,
_ = Logger.debug("title #{inspect(%{attributes: title})}"),
{k, v} <- title do
IO.puts "#{k} --> #{v}"
Repo.insert(%PlaylistTitle{language_id: k, localizedname: v, uuid: Ecto.UUID.generate(), playlist_id: playlist.id})
end
Logger.debug("maps #{inspect(%{attributes: maps})}")
{:ok, maps}
【讨论】: