@Shantanu48114860 First of all good naming would definitely help us understand your code much more, so please don’t forget about that. If I understand correctly your problem then you should simply use Enum.reduce/3
like this:
new_value = 1
values = List.duplicate(0, 5) # [0, 0, 0, 0, 0] in nicer form :-)
indexes = [1, 4]
Enum.reduce(indexes, values, &List.replace_at(&2, &1, new_value))
Following Enum.reduce/3
documentation:
@spec reduce(t(), any(), (element(), any() → any())) :: any()
Invokes fun for each element in the enumerable with the accumulator.
The initial value of the accumulator is acc. The function is invoked for each
element in the enumerable with the accumulator. The result returned by the
function is used as the accumulator for the next iteration. The function
returns the last accumulator.
In other words:
- 1st argument is enumerable (
indexes
) - for each element of it we would call some function
- 2nd argument is accumulator (
values
) - it’s a default value which would be changed in each function call
- 3rd argument is function - after each call accumulator is changed and is passed again to that function until your enumerable (
indexes
) becomes empty.
&List.replace_at(&2, &1, new_value)
is a shorthand to:
fn arg1, arg2 -> List.replace(arg2, arg1, new_value) end
.
First 2 arguments are passed by Enum.reduce/3
. First agument is element
(here index). Second is accumulator
. It’s why we are passing &2
before &1
in List.replace_at/3
.
Finally here is fragment from List.replace_at/3
documentation:
Returns a list with a replaced value at the specified index
.
HINT:
If you are going to delete or insert elements by indexes
then please make sure you are doing it in reverse order as otherwise you would hit a conflict of indexes.
Here goes some examples:
# those variables are not going to change in all examples
new_value = 1
values = Enum.to_list(0..9)
indexes = [1, 4]
# Firstly List.delete_at/2:
# WRONG:
Enum.reduce(indexes, values, &List.delete_at(&2, &1))
# returns: [0, 2, 3, 4, 6, 7, 8, 9]
# GOOD:
indexes |> Enum.reverse() |> Enum.reduce(values, &List.delete_at(&2, &1))
# returns: [0, 2, 3, 5, 6, 7, 8, 9]
# Same goes to List.insert_at/3:
# WRONG:
Enum.reduce(indexes, values, &List.insert_at(&2, &1, new_value))
# returns: [0, 1, 1, 2, 1, 3, 4, 5, 6, 7, 8, 9]
# GOOD:
indexes |> Enum.reverse() |> Enum.reduce(values, &List.insert_at(&2, &1, new_value))
# returns: [0, 1, 1, 2, 3, 1, 4, 5, 6, 7, 8, 9]
As you can see in first example instead of 4
value we wanted to remove 5
value and in second example secondly inserted 1
value is after 2
instead of 3
. It’s why order of processed indexes
is important!
Helpful resources:
- Enum.reduce/3
- Enum.reverse/1
- List.delete_at/2
- List.insert_at/2
- List.replace_at/2
- Partials and function captures in Elixir