Python 3.x: combina una lista de diccionarios con una coincidencia de valor clave

CorePress2024-01-25  90

listofdicts = [
{
    "if-e0": "e0",
    "ip-add-e0": "192.168.1.1",
    "name": "host1"
},
{
    "if-e1": "e1",
    "ip-add-e1": "192.168.2.1",
    "name": "host1"
},
{
    "if-e1": "e1",
    "ip-add-e1": "172.16.1.1",
    "name": "host2"
},
{
    "if-e2": "e2",
    "ip-add-e2": "172.16.2.1",
    "name": "host2"
}]

Resultado esperado:

listofdicts = [
{
    "if-e0": "e0",
    "ip-add-e0": "192.168.1.1",
    "if-e1": "e1",
    "ip-add-e1": "192.168.2.1",
    "name": "host1"
},
{
    "if-e1": "e1",
    "ip-add-e1": "172.16.1.1",
    "if-e2": "e2",
    "ip-add-e2": "172.16.2.1",
    "name": "host2"
}]

He intentado que esto funcione, pero aún no he tenido suerte; la lista real tiene más de 60 000 dictados con hosts únicos y coincidentes.

Podría ser más fácil de resolver, pero para mí ha sido una pesadilla desde hace unas horas.

Agradecemos su ayuda.

Saludos, Avinash

1

¡Hola Avinash! Visite stackoverflow.com/help/formatting para aclarar el formato de su pregunta. Ayuda a otros a comprender mejor su código y su problema y podrán ayudarlo.Eres mucho más rápido.

-Aman Kumar

28/03/2021 a las 16:14

Vale, ya hemos solucionado el formato, ¿todavía no estás bien? Gracias

- Avinash Rai

28/03/2021 a las 16:20



------------------------------------

La teoría de grafos parece ser útil en este caso.

Para resolver esto, necesita crear un gráfico, donde cada vértice se relacione con un diccionario de su lista de entrada.

Debe haber un borde entre dos vértices si hay una clave común-par de valores en los diccionarios correspondientes (más específicamente, para los diccionarios d1 y d2 debería haber una ventaja if len(set(d1.items()).intersection(d2.items())) != 0 o, más simple, if set(d1.items()).intersection(d2.items()). La condición significa que hay al menos un par clave-valor en la intersección de los conjuntos de elementos de d1 y d2).

Una vez creado el gráfico, debe encontrar todos los componentes de conectividad (es una DFS (búsqueda en profundidad) bastante simple; puede buscarla en Google si no está familiarizado con los algoritmos de gráficos). Los diccionarios de cada componente de conectividad deben combinarse en uno: debe haber un diccionario resultante por componente. La lista de estos diccionarios resultantes es tu respuesta.

Aquí tienes un ejemplo de cómo combinar algunos diccionarios:

connectivity_component_dicts = [{...}, ...]
resulting_dict = {**d for d in connectivity_component_dicts}
# Note that the greater the index of `d` in `connectivity_component_dicts`,
# the higher priority its keys have if there are same keys in some dicts.

3

Muchas gracias, lo intentaré.

- Avinash Rai

28/03/2021 a las 16:43

@AvinashRai, buena suerte. No dudes en pedir ayuda si te quedas atascado o te das cuenta de que no entiendes algo en mi explicación

- Kolay.Ne

28/03/2021 a las 17:12

Hola @kolay.Ne, sí, funcionó. Esta fue una manera fantástica de resolverlo, aunque probé un enfoque diferente

- Avinash Rai

31 de marzo de 2021 a las 18:26



------------------------------------

@Kolay.Ne Hola, chicos, Funcionó con un truco muy básico. El método gráfico es fantástico para resolverlo, aunque utilicé el siguiente enfoque que funcionó:

for d in listofdicts:
    x = listofdicts.index(d)
    for y in range(len(listofdicts)):
        k = 'name'
        if y != x and y < len(listofdicts):
            if listofdicts[x][k] == listofdicts[y][k]:
                dc = copy.deepcopy(listofdicts[y])
                listofdicts[x].update(dc)
                listofdicts.remove(dc)

Podrían haber otros enfoques para resolverlo, estoy seguro de que la forma patónica será solo un par de líneas, esto resolvió mi problema para el trabajo en cuestión.

Gracias a kolay.Ne por responder rápidamente e intentar ayudar, y el método gráfico también es fantástico, requiere codificación profesional y seguramente será más escalable.



------------------------------------

a = []

for i in listofdicts:
    if i["name"] not in a:
        a.append(i["name"])
        print(i)

2

Parece que no siempre resuelve el problema (no había nada sobre las claves de nombre en la declaración) ni siquiera produce el exresultado esperado

- Kolay.Ne

28/03/2021 a las 16:29

Muchas gracias por la respuesta rápida, pero sobrescribe una de las interfaces de una instancia host1 a la que le falta su e1 en la nueva lista a, lo que produce lo siguiente: <b>{'if-e0': & #39;e0', 'ip-add-e0': '192.168.1.1', 'nombre': 'host1' } <b>, y al host2 le falta e2.

- Avinash Rai

28 de marzo de 2021 a las 16:34

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare