Hacer un diccionario con claves duplicadas en Python

8 minutos de lectura

Hacer un diccionario con claves duplicadas en Python
nrj

Tengo la siguiente lista que contiene números de registro de automóviles duplicados con diferentes valores. Quiero convertirlo en un diccionario que acepte estas claves múltiples de números de registro de automóviles.

Hasta ahora, cuando intento convertir la lista en diccionario, elimina una de las claves. ¿Cómo hago un diccionario con claves duplicadas?

La lista es:

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

El código que he probado es:

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()

  • Si un diccionario permitiera claves duplicadas con diferentes valores asociados, ¿cuál esperaría recuperar cuando busque el valor de dicha clave más adelante?

    – martineau

    19 mayo 2012 a las 12:17

1646961670 132 Hacer un diccionario con claves duplicadas en Python
NPE

Los diccionarios de Python no admiten claves duplicadas. Una forma de evitarlo es almacenar listas o conjuntos dentro del diccionario.

Una manera fácil de lograr esto es usando defaultdict:

from collections import defaultdict

data_dict = defaultdict(list)

Todo lo que tienes que hacer es reemplazar

data_dict[regNumber] = details

con

data_dict[regNumber].append(details)

y obtendrás un diccionario de listas.

  • Al principio, no entendí que esto es equivalente a declarar el valor de la clave del diccionario como una lista y agregarlo. Sin embargo, elimina algunas líneas repetitivas, lo cual es bueno. if not my_key in data_dict: data_dict[my_key] = list()

    – ThorSummoner

    30 de abril de 2015 a las 23:03

1646961671 274 Hacer un diccionario con claves duplicadas en Python
escorpión

Puede cambiar el comportamiento de los tipos integrados en Python. Para su caso, es realmente fácil crear una subclase de dictado que almacenará valores duplicados en listas bajo la misma clave automáticamente:

class Dictlist(dict):
    def __setitem__(self, key, value):
        try:
            self[key]
        except KeyError:
            super(Dictlist, self).__setitem__(key, [])
        self[key].append(value)

Ejemplo de salida:

>>> 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]}

  • ¿Por qué no solo if key not in self: en lugar de try:/except KeyError:?

    – Kirill Bulyguin

    3 de enero de 2017 a las 18:51


  • ¿No es esto lo mismo que: ‘from collections import defaultdict d = defaultdict(list) d[‘test’].agregar(1) d[‘test’].agregar(2) d[‘test’].append(3)’ ¿O me estoy perdiendo algo?

    – Kane Chew

    28/10/2017 a las 21:01


  • @kirill docs.python.org/3.4/glossary.html#term-eafp

    – Drdilyor

    24 de mayo de 2021 a las 10:07

1646961671 90 Hacer un diccionario con claves duplicadas en Python
DonCalisto

¡No puede tener un dictado con claves duplicadas para la definición! En su lugar, puede usar una sola clave y, como valor, una lista de elementos que tenían esa clave.

Así que puedes seguir estos pasos:

  1. Vea si la clave del elemento actual (de su conjunto inicial) está en el dict final. Si es así, vaya al paso 3
  2. Actualizar dictado con clave
  3. Agregue el nuevo valor al dict[key] lista
  4. Repetir [1-3]

Acabo de publicar una respuesta a una pregunta que posteriormente se cerró como un duplicado de esta (creo que por buenas razones), pero me sorprende ver que mi solución propuesta no está incluida en ninguna de las respuestas aquí.

En lugar de usar un defaultdict o jugando con las pruebas de membresía o el manejo manual de excepciones, puede agregar fácilmente valores a las listas dentro de un diccionario usando el setdefault método:

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!

Esto es muy parecido a usar un dictado predeterminado, pero no necesita un tipo de datos especial. Cuando usted llama setdefault, comprueba si el primer argumento (la clave) ya está en el diccionario. Si no encuentra nada, asigna el segundo argumento (el valor predeterminado, una lista vacía en este caso) como un nuevo valor para la clave. Si la clave existe, no se hace nada especial (el valor predeterminado no se usa). Sin embargo, en cualquier caso, el valor (ya sea antiguo o nuevo) se devuelve, por lo que podemos llamar incondicionalmente append en él, sabiendo que siempre debe ser una lista.

1646961672 948 Hacer un diccionario con claves duplicadas en Python
xiandulce

Puedes consultar el siguiente artículo:
http://www.wellho.net/mouth/3934_Multiple-identical-keys-in-a-Python-dict-yes-you-can-.html

En un dict, si una clave es un objeto, no hay problemas de duplicación.

Por ejemplo:

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}

  • ¿Cómo obtener todos los valores con la tecla ‘k’? La única forma de hacer esto es comparando secuencialmente, lo que pierde el significado de usar un diccionario hash.

    – siervo

    2 de noviembre de 2018 a las 9:36

  • Respuesta limpia y elegante. ¡Gracias! El corolario es que, si ya planea usar objetos, no necesita hacer nada. Vea el ejemplo completo usando OrderedDict: stackoverflow.com/a/56959984/1732392

    – Feiteira

    9 julio 2019 a las 20:20

  • @minion está justo aquí. O almacena referencias a esos objetos para acceder a los valores, o tiene que iterar. En el primer caso, también podría poner los datos en el objeto clave y olvidarse del diccionario, en el último caso, puede usar una lista de tuplas. Esto realmente no hace lo que dice en la lata, solo está haciendo que las teclas sean diferentes. Eso podría resolver su problema, pero en ese momento, el diccionario se convierte en la estructura de datos incorrecta y solo tiene una capa de direccionamiento indirecto que no necesita.

    – Gareth Latty

    9 de julio de 2019 a las 20:34

  • De acuerdo, esta solución funciona perfectamente para los casos en los que solo necesita un dict y no desea recuperar los valores a través de la clave o algo así, en otras palabras, no necesita hacer nada más que obtener la estructura de datos.

    – 0xInfección

    25 de agosto de 2020 a las 5:28

1646961672 261 Hacer un diccionario con claves duplicadas en Python
Pedro Mortensen

Si quieres tener listas solo cuando son necesariasy valores en cualquier otro caso, entonces puede hacer esto:

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])

A continuación, puede hacer lo siguiente:

dl = DictList()
dl['a']  = 1
dl['b']  = 2
dl['b'] = 3

Que almacenará lo siguiente {'a': 1, 'b': [2, 3]}.


Tiendo a usar esta implementación cuando quiero tener diccionarios inverso/inversoen cuyo caso simplemente hago:

my_dict = {1: 'a', 2: 'b', 3: 'b'}
rev = DictList()
for k, v in my_dict.items():
    rev_med[v] = k

Lo que generará el mismo resultado que el anterior: {'a': 1, 'b': [2, 3]}.


ADVERTENCIA: Esta implementación se basa en la inexistencia de la append método (en los valores que está almacenando). Esto podría producir resultados inesperados si los valores que está almacenando son listas. Por ejemplo,

dl = DictList()
dl['a']  = 1
dl['b']  = [2]
dl['b'] = 3

produciría el mismo resultado que antes {'a': 1, 'b': [2, 3]}pero uno podría esperar lo siguiente: {'a': 1, 'b': [[2], 3]}.

  • ¿Cómo obtener todos los valores con la tecla ‘k’? La única forma de hacer esto es comparando secuencialmente, lo que pierde el significado de usar un diccionario hash.

    – siervo

    2 de noviembre de 2018 a las 9:36

  • Respuesta limpia y elegante. ¡Gracias! El corolario es que, si ya está planeando usar objetos, entonces no necesita hacer nada. Vea el ejemplo completo usando OrderedDict: stackoverflow.com/a/56959984/1732392

    – Feiteira

    9 julio 2019 a las 20:20

  • @minion está justo aquí. O almacena referencias a esos objetos para acceder a los valores, o tiene que iterar. En el primer caso, también podría poner los datos en el objeto clave y olvidarse del diccionario, en el último caso, puede usar una lista de tuplas. Esto realmente no hace lo que dice en la lata, solo está haciendo que las teclas sean diferentes. Eso podría resolver su problema, pero en ese momento, el diccionario se convierte en la estructura de datos incorrecta y solo tiene una capa de direccionamiento indirecto que no necesita.

    – Gareth Latty

    9 de julio de 2019 a las 20:34

  • De acuerdo, esta solución funciona perfectamente para los casos en los que solo necesita un dict y no desea recuperar los valores a través de la clave o algo así, en otras palabras, no necesita hacer nada más que obtener la estructura de datos.

    – 0xInfección

    25 de agosto de 2020 a las 5:28

1646961672 261 Hacer un diccionario con claves duplicadas en Python
Pedro Mortensen

No puede tener claves duplicadas en un diccionario. Usa un dictado de listas:

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)

  • Pero el defaultdict la solución es mejor que hacer esto manualmente (respuesta de aix)

    – Oskarbí

    19 mayo 2012 a las 11:57


  • en lugar de hash_keysolo podemos usar if not regNumber in data_dict

    – Niklas B.

    19 mayo 2012 a las 12:34

  • Sí, not in es mejor y de hecho no hay hash_key método en Python 3.x. ¡Gracias!

    – Oskarbí

    19 mayo 2012 a las 12:45

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad