Я хочу изменить определенную часть кортежа. Можно ли использовать сопоставление с образцом?
{1, [{:reach, [:s, :d]}, [link: [:s, :d]]]}
Я хочу изменить охват на :reach_1
. Я могу получить поле охвата, но не могу изменить весь кортеж.
{id, [{item, _}, _]} = {1, [{:reach, [:s, :d]}, [link: [:s, :d]]]}
:"#{item}_#{id}"
Как я могу добавить его обратно в кортеж, заменив :reach
?
Если кортеж всегда имеет одинаковую структуру, вы можете извлечь фиксированную часть и составить новый кортеж:
> {a, [{_, b}, c]} = {1, [{:reach, [:s, :d]}, [link: [:s, :d]]]}
> {a, [{:reach_1, b}, c]}
В Эликсире вы не можете изменить структуру данных, вы можете создать ее модифицированную копию.
На самом деле в модуле Kernel
есть функция put_elem, которая создает новый кортеж с обновленным элементом, но в вашем случае код будет сложным, поскольку вам нужно изменить элемент внутри вложенного списка/кортежа.
Не использовать сопоставление с образцом, потому что вам фактически придется снова записывать полный кортеж. put_in/3 предназначен для помещения данных во вложенные структуры. Вы можете добиться желаемого, используя его с Access.elem/1 и Access.at!/1:
{id, [{item, _}, _]} = foo = {1, [{:reach, [:s, :d]}, [link: [:s, :d]]]}
put_in(foo, [Access.elem(1), Access.at!(0), Access.elem(0)], :"#{item}_#{id}")
Или просто снова напишите кортеж:
{id, [{item, rest1}, rest2]} = {1, [{:reach, [:s, :d]}, [link: [:s, :d]]]}
{id, [{:"#{item}_#{id}", rest1}, rest2]}
Результат в обоих случаях:
{1, [{:reach_1, [:s, :d]}, [link: [:s, :d]]]}
Именно то, что я искал. Это структура журнала данных, и она всегда будет одинаковой. Следовательно, pattern matching
будет лучшим вариантом. Спасибо
Вы можете рассмотреть возможность использования карты, если вам нужна структура данных, которую нужно часто/легко изменять.