Копировать кортеж с модификацией - PullRequest
3 голосов
/ 23 февраля 2020

У меня есть кортеж:

my_tup=(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9)

Я хотел бы изменить значение в этом кортеже. Поскольку кортежи являются неизменяемыми, очевидный маршрут не работает:

my_tup[:a]=50 #Raises an error, as expected

Поэтому, чтобы выполнить модификацию, я хотел бы скопировать кортеж и его элементы при изменении целевого элемента.

Мое текущее решение выглядит следующим образом:

my_tup=(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9)
args = keys(my_tup)
NamedTuple{args}(i!=:a ? getfield(my_tup, i) : 50 for i in args)

Но это кажется многословным или как будто в стандартной библиотеке уже должна быть функция для него.

Есть ли лучший способ?

Ответы [ 3 ]

3 голосов
/ 23 февраля 2020

Вы можете merge два именованных кортежа:

julia> xs = (a = 1, b = 2, c = 3)
(a = 1, b = 2, c = 3)

julia> ys = merge(xs, (; a = 50))
(a = 50, b = 2, c = 3)
2 голосов
/ 23 февраля 2020

Дэвид Варела имеет правильный ответ: «используйте merge». Это важная техника.

  • Чтобы сделать это решение более доступным для других, вот несколько примеров.

при создании обычные кортежи (безымянные кортежи) и именованные кортежи

Оба кортежа и именованные кортежи создаются с использованием круглых скобок:

julia> a_tuple = (1, 2)
(1, 2)

julia> a_namedtuple = (a = 1, b = 2)
(a = 1, b = 2)

Если мы попытаемся создать кортеж или именованный кортеж с ровно одной записью, то же самое кстати, это не работает; вместо этого значениям присваиваются именованные переменные напрямую.

julia> not_a_tuple = ("xyz");
julia> not_a_tuple, typeof(not_a_tuple)
("xyz", String)

julia> not_a_namedtuple = (abc = "xyz");
julia> not_a_namedtuple, typeof(not_a_namedtuple)
("xyz", String)

Чтобы создать кортежи и именованные кортежи, которые имеют одно значение, мы дадим Джулии знать, что мы работаем с [именованными] кортежами. Простой способ сделать это, и тот, который работает для обоих типов кортежей, состоит в добавлении запятой '' 'перед закрывающей скобкой. Для наглядности я отделяю запятые от значений; это не обязательно делать в исходном коде.

julia> a_tuple = (0.5 ,)
(0.5,)

julia> a_namedtuple = (onehalf = 0.5 ,)
(onehalf = 0.5,)

при замене значений в NamedTuples

julia> namedtuple = (a = 1, b = 2, c = 3);  # the initial NamedTuple
julia> changes_to_make = (b = 0 ,);         # the modifications intended

julia> changed_namedtuple = merge(namedtuple, changes_to_make)
(a = 1, b = 0, c = 3)
julia> namedtuple = (a = 1, b = 2, c = 3);  # the initial NamedTuple
julia> changes_to_make = (b = 0, c = 7);    # the modifications intended

julia> changed_namedtuple = merge(namedtuple, changes_to_make)
(a = 1, b = 0, c = 7)
1 голос
/ 23 февраля 2020
julia> my_tup=(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8,i=9)
(a = 1, b = 2, c = 3,d = 4, e = 5, f = 6, g = 7, h = 8, i = 9)

julia> new_one = (my_tup..., a=50)
(a = 50, b = 2, c = 3, d = 4, e = 5, f = 6, g = 7, h = 8, i = 9)
...