Подтвердить что ты не робот

Создать словарь с дубликатами ключей в 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()
4b9b3361

Ответ 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

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

Таким образом, вы можете выполнить следующие шаги:

  1. Посмотрите, находится ли ключ текущего элемента (вашего начального набора) в последнем слове. Если это так, перейдите к шагу 3
  2. Обновить dict ключом
  3. Добавить новое значение в список dict [key]
  4. Повторите [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, зная, что оно всегда должно быть списком.