Создать словарь с дубликатами ключей в Python
У меня есть следующий список, который содержит дубликаты регистрационных номеров автомобилей с различными значениями. Я хочу преобразовать его в словарь, который принимает несколько ключей регистрационных номеров автомобилей.
До сих пор, когда я пытаюсь преобразовать список в словарь, он исключает один из ключей. Как сделать словарь с дубликатами ключей?
Список:
EDF768, Bill Meyer, 2456, Vet_Parking
TY5678, Jane Miller, 8987, AgHort_Parking
GEF123, Jill Black, 3456, Creche_Parking
ABC234, Fred Greenside, 2345, AgHort_Parking
GH7682, Clara Hill, 7689, AgHort_Parking
JU9807, Jacky Blair, 7867, Vet_Parking
KLOI98, Martha Miller, 4563, Vet_Parking
ADF645, Cloe Freckle, 6789, Vet_Parking
DF7800, Jacko Frizzle, 4532, Creche_Parking
WER546, Olga Grey, 9898, Creche_Parking
HUY768, Wilbur Matty, 8912, Creche_Parking
EDF768, Jenny Meyer, 9987, Vet_Parking
TY5678, Jo King, 8987, AgHort_Parking
JU9807, Mike Green, 3212, Vet_Parking
Код, который я пробовал:
data_dict = {}
data_list = []
def createDictionaryModified(filename):
path = "C:\Users\user\Desktop"
basename = "ParkingData_Part3.txt"
filename = path + "//" + basename
file = open(filename)
contents = file.read()
print contents,"\n"
data_list = [lines.split(",") for lines in contents.split("\n")]
for line in data_list:
regNumber = line[0]
name = line[1]
phoneExtn = line[2]
carpark = line[3].strip()
details = (name,phoneExtn,carpark)
data_dict[regNumber] = details
print data_dict,"\n"
print data_dict.items(),"\n"
print data_dict.values()
Ответы
Ответ 1
Словари Python не поддерживают дубликаты ключей. Один из способов - хранить списки или наборы внутри словаря.
Один простой способ добиться этого - использовать defaultdict
:
from collections import defaultdict
data_dict = defaultdict(list)
Все, что вам нужно сделать, это заменить
data_dict[regNumber] = details
с
data_dict[regNumber].append(details)
и вы получите словарь списков.
Ответ 2
Вы можете изменить поведение встроенных типов в Python. Для вашего случая действительно легко создать подкласс dict, который будет автоматически хранить дублированные значения в списках под одним и тем же ключом:
class Dictlist(dict):
def __setitem__(self, key, value):
try:
self[key]
except KeyError:
super(Dictlist, self).__setitem__(key, [])
self[key].append(value)
Пример вывода:
>>> d = dictlist.Dictlist()
>>> d['test'] = 1
>>> d['test'] = 2
>>> d['test'] = 3
>>> d
{'test': [1, 2, 3]}
>>> d['other'] = 100
>>> d
{'test': [1, 2, 3], 'other': [100]}
Ответ 3
Вы не можете иметь диктат с дубликатами ключей для определения! Вместо этого вы можете использовать один ключ и, в качестве значения, список элементов, которые имели этот ключ.
Таким образом, вы можете выполнить следующие шаги:
- Посмотрите, находится ли ключ текущего элемента (вашего начального набора) в последнем слове. Если это так, перейдите к шагу 3
- Обновить dict ключом
- Добавить новое значение в список dict [key]
- Повторите [1-3]
Ответ 4
Если вы хотите иметь списки только тогда, когда они необходимы, и значения в любых других случаях, то вы можете сделать это:
class DictList(dict):
def __setitem__(self, key, value):
try:
# Assumes there is a list on the key
self[key].append(value)
except KeyError: # If it fails, because there is no key
super(DictList, self).__setitem__(key, value)
except AttributeError: # If it fails because it is not a list
super(DictList, self).__setitem__(key, [self[key], value])
Затем вы можете сделать следующее:
dl = DictList()
dl['a'] = 1
dl['b'] = 2
dl['b'] = 3
Который будет хранить следующее {'a': 1, 'b': [2, 3]}
.
Я склонен использовать эту реализацию, когда я хочу иметь обратные/обратные словари, и в этом случае я просто делаю:
my_dict = {1: 'a', 2: 'b', 3: 'b'}
rev = DictList()
for k, v in my_dict.items():
rev_med[v] = k
Который будет генерировать тот же вывод, что и выше: {'a': 1, 'b': [2, 3]}
.
CAVEAT: эта реализация основана на несуществовании метода append
(в значениях, которые вы храните). Это может привести к неожиданным результатам, если значения, которые вы храните, являются списками. Например,
dl = DictList()
dl['a'] = 1
dl['b'] = [2]
dl['b'] = 3
выдаст тот же результат, что и раньше {'a': 1, 'b': [2, 3]}
, но можно ожидать следующего: {'a': 1, 'b': [[2], 3]}
Ответ 5
Вы не можете иметь дублированные ключи в словаре. Используйте подсказку списков:
for line in data_list:
regNumber = line[0]
name = line[1]
phoneExtn = line[2]
carpark = line[3].strip()
details = (name,phoneExtn,carpark)
if not data_dict.has_key(regNumber):
data_dict[regNumber] = [details]
else:
data_dict[regNumber].append(details)
Ответ 6
Вы можете обратиться к следующей статье: http://www.wellho.net/mouth/3934_Multiple-identical-keys-in-a-Python-dict-yes-you-can-.html
В диктовке, если ключ является объектом, нет повторяющихся проблем.
Например:
class p(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return self.name
def __str__(self):
return self.name
d = {p('k'): 1, p('k'): 2}
Ответ 7
Я только что опубликовал ответ на вопрос, который впоследствии был закрыт как дубликат этого (по уважительным причинам, я думаю), но я удивлен, увидев, что мое предлагаемое решение не включено ни в один из ответов здесь.
Вместо того, чтобы использовать defaultdict
или возиться с тестами членства или ручной обработкой исключений, вы можете легко добавлять значения в списки в словаре, используя метод setdefault
:
results = {} # use a normal dictionary for our output
for k, v in some_data: # the keys may be duplicates
results.setdefault(k, []).append(v) # magic happens here!
Это очень похоже на использование defaultdict, но вам не нужен специальный тип данных. Когда вы вызываете setdefault
, он проверяет, есть ли первый аргумент (ключ) в словаре. Если ничего не находит, он назначает второй аргумент (значение по умолчанию, пустой список в данном случае) в качестве нового значения для ключа. Если ключ существует, ничего особенного не делается (значение по умолчанию не используется). Однако в любом случае возвращается значение (старое или новое), поэтому мы можем безоговорочно вызвать append
, зная, что оно всегда должно быть списком.