【问题标题】:elixir fill a list with for loop长生不老药用 for 循环填充列表
【发布时间】:2020-01-24 19:52:36
【问题描述】:

我想用 for 循环填充一个列表。我检查了这篇文章here,这有理由说明为什么下面的代码不会这样做,但是我的代码将是什么来实现它。我是 elixir 的新手,来自 Java 背景

old_data = ['a','b','c','d']
new_data = []
for data <- old_data do
  new_data = List.insert_at(new_data, -1, data)
  IO.puts(new_data)
end
IO.puts(old_data)
IO.puts("new data is #{new_data}.")

在向new_data 添加元素之前,我需要做一些操作,所以new_data = old_data 不是我要找的东西

【问题讨论】:

  • new_data = old_data 会更简洁
  • 由于作用域,代码不会这样做。
  • @GavinBrelstaff:感谢您的意见。在将元素添加到 new_data 之前,我需要做一些操作,所以 new_data = old_data 不是我要找的东西。
  • 哎呀,我错过了 new_data 正在附加元素,返回 not reversed 列表的事实。我更新了答案。

标签: for-loop elixir


【解决方案1】:

Elixir (与 Java 不同)是不可变的。也就是说,一个不能就地修改任何数据。此外,没有 for 循环。根本没有循环。 Kernel.SpecialForms.for/1理解

也就是说,如果你想产生新列表,你应该明确地这样做。不幸的是,Kernel.SpecialForms.for/1 是不可能的。我们通常为此使用递归。

defmodule Reverser do
  def go(input, output \\ [])                  # header
  def go([], output), do: Enum.reverse(output) # termination
  def go([h | t], output), do: go(t, [h | output])
end

Reverser.go([1, 2, 3])
#⇒ [1, 2, 3]

此外,这里我们在终止时使用Enum.reverse/1,因为我们在递归期间添加到列表中,与附加链接列表相比,这是一种更快的方法。


旁注:IO.puts/1 的输出可能会造成混淆,请改用 IO.inspect/3

IO.inspect([1, 2, 3], label: "List")
#⇒ List: [1, 2, 3]

旁注 #2: ['a','b','c','d'] 是一个列表列表。如果您想要一个字符/字符串列表,请使用 双引号。是的,单引号和双引号的含义截然不同。

is_list('a')
#⇒ true
'a' == [97]
#⇒ true

【讨论】:

    【解决方案2】:

    Aleksei 提到了一个很好的起点,但是一旦您了解了递归的工作原理,您就可以使用 Enum 函数(如 Enum.map/2)使代码更简洁,当然这取决于具体情况:

    old_data = ['a','b','c','d']
    Enum.map(old_data, fn _el -> -1 end)
    #⇒ [-1, -1, -1, -1]
    

    【讨论】:

    • 还有Enum.reduce/3 瑞士刀 :)
    • 确实如此,尤其是因为 elixir 是动态类型的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-01
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-23
    相关资源
    最近更新 更多