#elixir
Вопрос:
Я хочу заменить все вхождения 2 на 3.Я хочу сделать это без использования значения индекса, потому что это было бы жестким кодированием. То, что у меня есть до сих пор, — это:
list=[1,2,3,4,2,34,2]
replace_at(list, index, value)
Enum.each list, fn(x) ->
if x==2 do
replace_at(list, index, 3)
end
Enum.each list, fn(x) ->
IO.puts x
end
Ответ №1:
В Elixir у вас нет массивов, но есть связанный список. Если вы просто хотите заменить все значения 2 на 3, вы можете использовать функцию карты Enum
модуля, как это:
iex(1)> Enum.map(list, fn x -> if x == 2, do: 3, else: x end)
[1, 3, 3, 4, 3, 34, 3]
Вы также можете использовать сопоставление шаблонов:
iex(1)> Enum.map(list, fn
...(1)> 2 -> 3
...(1)> x -> x
...(1)> end)
Комментарии:
1. Вы можете даже однострочно:
Enum.map(list, fn 2 -> 3; x -> x end)
(но ненадолго, так как форматер по умолчанию преобразует его в многострочный, если вы его используете).
Ответ №2:
Важно знать, что Эликсир неизменен, поэтому вы не можете заменить значения в списке; на самом деле вы создаете новый список.
Вы можете использовать метод map из модуля перечисления, где вы можете найти множество алгоритмов для работы с перечисляемыми объектами.
iex(2)> [1, 2, 3, 4, 2, 34, 2] |> Enum.map(fn
...(2)> 2 -> 3
...(2)> other -> other
...(2)> end)
[1, 3, 3, 4, 3, 34, 3]
Метод с такой реализацией может быть похож на приведенный ниже код:
defmodule Replace do
def replace_all(list, from, to) do
list
|> Enum.map(fn
^from -> to
other -> other
end)
end
end
Ответ №3:
У нас нет массивов, и доступ по индексу обходится дорого.
Если вы все еще хотите этого добиться, Enum.with_index/2
это ваш друг.
replace_at = fn list, index, value ->
list
|> Enum.with_index()
|> Enum.map(fn
{_, ^index} -> value # match index
{value, _} -> value # anything else
end)
end
И используйте его, как
# index 0 1 2 3 4 5 6
replace_at.([1, 2, 3, 4, 2, 34, 2], 2, 42)
#⇒ [1, 2, 42, 4, 2, 34, 2]
Замена всех 2 не имеет ничего общего с индексом, для этого не нужен индекс. Просто используйте Enum.map/2
из коробки.
Кроме того, вы должны усвоить, что Enum.each/2
это никогда ничего не меняет.
Комментарии:
1. Re: replace_at:
List.replace_at/3
сделал бы то же самое из коробки и, я полагаю, был бы более эффективным, поскольку он должен иметь возможность повторно использовать правую часть списка и не должен проходить весь список (но это все равно дорого и не эквивалентно массиву).2. Цель этого ответа состояла в основном в том, чтобы показать, как мы работаем с индексами в списках, если это необходимо.
Enum.reduce_while/3
вместоEnum.map/2
этого и мы приступим кList.replace_at/3
реализации. Кроме того,put_in/3
Access.at/2
.