У меня есть этот словарь:
d = {'a': (1, 2, 'a'), 'b': (1, 2, 'b'), 'c': (2, 4, 'c'), 'd': (1, 3, 'd'), 'e': (0, 1, 'e'), 'f': (0, 1, 'f'), 'g': (1, 3, 'g'), 'h': (0, 1, 'h'), 'j': (1, 2, 'j'), 'i': (0, 1, 'i'), 'k': (-1, 0, 'k')}
Как можно вычесть значение на 1 для конкретной пары ключ/значение в этом словаре, если ключ соответствует параметру?
Например, я хочу вычесть значения ключа a на 1, чтобы он теперь отображал:
{'a': (0, 1, 'a')
Как я могу отредактировать значения этого конкретного ключа и уменьшить только целые числа на 1 при создании того же словаря снова?
Код до сих пор:
def matching(key_to_subtract):
for key, value in d.items():
if key_to_subtract == key:
matching("a")
Желаемый результат:
{'a': (0, 1, 'a'), 'b': (1, 2, 'b'), 'c': (2, 4, 'c'), 'd': (1, 3, 'd'), 'e': (0, 1, 'e'), 'f': (0, 1, 'f'), 'g': (1, 3, 'g'), 'h': (0, 1, 'h'), 'j': (1, 2, 'j'), 'i': (0, 1, 'i'), 'k': (-1, 0, 'k')}
Поскольку tuple
является неизменным, вы должны создать новый и связать его с ключом. Вам не нужно, однако, повторять dict
для поиска данного ключа. В этом весь смысл dict
:
def decrement(d, k):
# if k in d: # if you are not certain the key exists
d[k] = tuple(v-1 if isinstance(v, int) else v for v in d[k])
Вы не можете изменить содержимое кортежа. Так что вам нужно создать новый кортеж и назначить его на dict:
d = {'a': (1, 2, 'a'), 'b': (1, 2, 'b'), 'c': (2, 4, 'c')}
d['a'] = tuple( i - 1 if isinstance(i, int) else i for i in d['a'] )
# d become {'a': (0, 1, 'a'), 'b': (1, 2, 'b'), 'c': (2, 4, 'c')}
Поскольку кортежи являются неизменяемыми, вы должны снова перестроить кортеж и переназначить новый кортеж на тот же ключ, с которого вы его получили. Это может быть написано в 1-2 строки, используя понимание, но затруднит понимание, надеюсь, это поможет!
Использование выражений генератора
def matching(key_to_subtract):
# generator expression force evaluated as tuple
d[key_to_subtract] = tuple(item-1 if isinstance(item, int) else item for item in d.get(key_to_subtract))
Расширенная форма
d = {'a': (1, 2, 'a'), 'b': (1, 2, 'b'), 'c': (2, 4, 'c'), 'd': (1, 3, 'd'), 'e': (0, 1, 'e'), 'f': (0, 1, 'f'), 'g': (1, 3, 'g'), 'h': (0, 1, 'h'), 'j': (1, 2, 'j'), 'i': (0, 1, 'i'), 'k': (-1, 0, 'k')}
def matching(key_to_subtract):
buffer = [] # to build new tuple later from this list
for item in d.get(key_to_subtract): # get the tuple and iterate over
try:
buffer.append(item - 1) # subtract 1
except TypeError:
buffer.append(item) # append directly if its not integer
d[key_to_subtract] = tuple(buffer) # reassign the list as tuple
matching("a")
list
в памяти, и повторное append
изменяет размер базового массива списков, возможно, несколько раз.
Исходя из вашего вопроса, я предлагаю другой подход из вашего кода. Причина в том, что d.items() создает представление, которое хорошо для проверки, но не для обновления кода.
Поэтому я предлагаю использовать d.keys() для поиска экземпляра key_to_subtract. Затем измените кортеж на список (или вы можете использовать другой метод нарезки кортежа в нужной позиции, затем добавьте новое значение, которое может быть быстрее в случае большого кортежа), а затем замените этот ключ новым значением (после изменив его обратно из списка в кортеж):
def matching(key_to_subtract):
#check for key_to_subtract
#if found
if key_to_subtract in d.keys():
#change to list
lst_val = list(d[key_to_subtract])
#subtract the two values
lst_val[0]-=1
lst_val[1]-=1
#change back to tuple
tuple_val = tuple(lst_val)
#replace the old value of the same key with the new value
d[key_to_subtract] = tuple_val
на основе функций в: https://docs.python.org/3.7/library/stdtypes.html#dict-views
Вы можете сделать это так, как кортежи являются неизменными объектами.
d = {'a': (1, 2, 'a'), 'b': (1, 2, 'b'), 'c': (2, 4, 'c'), 'd': (1, 3, 'd'), 'e': (0, 1, 'e'), 'f': (0, 1, 'f'), 'g': (1, 3, 'g'), 'h': (0, 1, 'h'), 'j': (1, 2, 'j'), 'i': (0, 1, 'i'), 'k': (-1, 0, 'k')}
def change_value_by_key_pos(data, key, pos, step):
for k,v in data.items():
if k == key:
list_items = list(data[key])
list_items[pos] = list_items[pos]+step
data[key] = tuple(list_items)
return data
data = change_value_by_key_pos(d,'a',1,1)
print(data)