#python #python-3.x #dictionary #append
#python #python-3.x #словарь #добавить
Вопрос:
У меня есть словарь, подобный этому:
dct = {'one': 'value',
'two': ['value1','value2','value1'],
'three':['otherValue1','otherValue2','otherValue1'],
'dontCareAboutThisKey':'debug'}
Мне нужно удалить повторяющиеся значения из списков. Я написал функцию для этого:
no_dups = {}
for keys in dct:
if isinstance(dct[keys], list) and keys != 'dontCareAboutThisKey':
for value in dct[keys]:
if value not in no_dups.values():
no_dups[keys].append(value)
else:
no_dups[keys] = dct[keys]
Я проверяю, является ли значение текущего ключа списком. Если нет, он просто «копирует» ключ в no_dups
словарь. Если это список, а не ключ, который меня не волнует (дубликатов точно нет) — он должен проверить, существует ли текущее значение в no_dups.values()
и добавить его к текущему ключу. Проблема в том, что я получаю сообщение об ошибке:
KeyError: 'two:'
Я знаю, это потому, что я пытаюсь добавить значение к несуществующему ключу, но я понятия не имею, как с этим справиться и заставить его работать.
Комментарии:
1. В какой строке выдается ошибка?
2.
no_dups[keys].append(value)
Ответ №1:
Я думаю, что лучший способ справиться с одновременным добавлением ключа — это использовать setdefault()
метод dicts:
no_dups.setdefault(keys,[]).append(value)
Но вместо этого вы можете сделать это более аккуратным способом, вот так:
#remove duplicates
no_dups = {k:list(set(v)) if isinstance(v, list) and k != 'dontCareAboutThisKey' else v
for k,v in dct.items()} # or dct.iteritems() if using python2.x
Этот взлом для комбинаций ключ-значение, которые проходят if
тест, преобразует список в набор (удаляя дубликаты), а затем снова в список. Для других комбинаций ключ-значение это оставит его нетронутым.
Комментарии:
1. Это довольно сложно понять, но я попытаюсь. Спасибо 🙂
2. Отлично, в этом нет никакой магии, Python действительно силен в понимании и хорош для их применения.
3. Я знаю, я знаю .. но
Learning Python
в нем 1500 страниц, и я не могу читать так быстро. Еще раз спасибо за ответ 🙂
Ответ №2:
dct = {'one': 'value',
'two': ['value1','value2','value1'],
'three':['otherValue1','otherValue2','otherValue1'],
'dontCareAboutThisKey':'debug'}
set(dct)
возвращает set
, который представляет собой список без дубликатов:
for key, value in dct.items():
if not isinstance(value, basestring):
dct[key] = set(value)
Если вам нужен новый словарь, вы могли бы сделать:
new_dct = {}
for key, value in dct.items():
if not isinstance(value, basestring):
new_dct[key] = set(value)
else:
new_dct[key] = value
Комментарии:
1. Я не уверен, действительно ли OP хочет создать копию, поскольку это приведет к редактированию на месте … но … мне кажется, это хороший подход
2. Я не знал об
set()
. Теперь это намного проще. Спасибо. Я хотел бы принять два ответа, но это невозможно. Пауло Бу был первым сset()
функцией, поэтому я принимаю его ответ, но я буду использовать ваш, потому что это не сложно для начинающего пользователя 🙂
Ответ №3:
Если вы хотите удалить дубликаты, просто измените свой список на set с помощью функции set():
https://docs.python.org/2/tutorial/datastructures.html#sets
Он автоматически предоставляет вам уникальный набор, после чего вы всегда можете изменить его обратно на list.
Комментарии:
1. Спасибо за информацию о наборах. Я запомню это 🙂