要修改相同的索引,我们可以做
mylist = [1,2,3]
Enum.map(mylist, fn x-> -x end) // [-1,-2,-3]
我们将如何修改其他索引,例如
for (i = 0; i < mylist.length; i++) {
mylist[i+1] = -mylist[i];
}
答案 0 :(得分:1)
最重要的是要记住,您必须创建一个全新的列表,因此您应该考虑如何最好地获得所需的内容,而不是如何复制用另一种语言来处理它的方式。
例如,如果您想将项目与附近的项目进行比较,则可以使用偏移量压缩列表:
iex> enum = 1..5
1..5
iex> stream = Stream.drop(enum, 1) # Enum.drop/2 would also work
#Stream<[enum: 1..5, funs: [#Function<48.15162342/1 in Stream.drop/2>]]>
iex> Enum.zip(enum, stream) # Stream.zip/2 works if you're going to iterate
[{1, 2}, {2, 3}, {3, 4}, {4, 5}]
对于您的特定示例,下一个值是先前取反的值,则可以创建无限流并获取所需的内容:
iex> 1 |> Stream.iterate(&-/1) |> Enum.take(3)
[1, -1, 1]
如果您只想修改一个值,则必须创建一个新列表,只更改新值(注意,这不是您要进行多次更新的方式) :
iex> {previous, [current | next]} = Enum.split(1..5, 3)
{[1, 2, 3], [4, 5]}
iex> Enum.concat([previous, [current * 12], next])
[1, 2, 3, 48, 5]
答案 1 :(得分:1)
到目前为止,这里的两个答案都是使用Enum.with_index/2
或Stream.iterate/2
或Enum.map/2
之类的Elixir核心库帮助程序。
我将展示伪指令示例中修改邻居索引的准系统功能方法。我将复制不会使VM崩溃的代码段。
> mylist = [ 1, 2, 3 ]
> for (i = 1; i < mylist.length; i++) { mylist[i-1] = -mylist[i] }
> mylist
//⇒ [ -2, -3, 3 ]
在Elixir中,使用递归将是:
defmodule Neighbour do
def map(list, acc \\ [])
def map([_, next | rest], acc), do: map(rest, [-next | acc])
def map([next], acc), do: Enum.reverse([next, -next | acc])
end
Neighbour.map([1, 2, 3])
#⇒ [-2, -3, 3]
答案 2 :(得分:0)
请记住,数据在Erlang中是不可变的,除非将命令式编程映射到函数式编程不是一个好主意,我们可以执行以下操作:
new_list = Enum.map(Enum.with_index(list), fn {v,i} ->
((Enum.at(list, i + 1) || 0) - v)
end)
哪个会导致[1, 1, -3]
或换句话说:
2 - 1 = 1
3 - 2 = 1
0 - 3 = -3
正如其他人指出的那样,按照Enum.at/2的O(n)复杂度,这样做将是一种低效的方法。
更高效,更惯用的解决方案是:
iex(1)> list0 = [1,2,3]
[1, 2, 3]
iex(2)> sliced = Enum.slice(list, 1, 2)
[2,3]
iex(3) list2 = List.duplicate(0, length(list0) - length(sliced))
[2, 3, 0]
iex(21)> Enum.map(Enum.zip(list, list2), fn({v1, v2}) -> v2 - v1 end)
[1, 1, -3]