Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

comparaison de dictionnaires et d'ensembles

+2 votes

Je désire comparer 2 dictionnaires.

Le premier comporte des ip qui sont déjà prises.

Le second comporte toutes les ip disponibles pour un réseau donné.

Objectif : ne garder que les ip qui sont disponibles dans ce réseau.

Je travaille avec Python 2.7.

Premier essai

reserved = {"formation" : ["192.168.0.1", "192.168.0.3"], "DR" : ["10.59.6.2", "10.59.6.3"]}
alls = {"formation" : ["192.168.0.1", "192.168.0.2", "192.168.0.3"], "DR" : ["10.59.6.2", "10.59.6.3", "10.59.6.4", "10.59.6.5"]}

for k, v in alls.iteritems():
    for ki, vi in reserved.iteritems():
        if k == ki:
            free[k] = set(v).difference(set(vi))

Ca fonctionne.

{'formation': set(['192.168.0.2']), 'DR': set(['10.59.6.4', '10.59.6.5'])}

Deuxième essai avec des dictionnaires résultant du module ipaddr généré avec la méthode .iterhosts()

reserved = {"formation" : [IPv4Address("192.168.0.1"), IPv4Address("192.168.0.3")], "DR" : [IPv4Address("10.59.6.2"),IPv4Address("10.59.6.3")]}
alls = {"formation" : [IPv4Address("192.168.0.1"), IPv4Address("192.168.0.2"), IPv4Address("192.168.0.3")], "DR" : [IPv4Address("10.59.6.2"), IPv4Address("10.59.6.3"), IPv4Address("10.59.6.4"), IPv4Address("10.59.6.5")]}

Ca ne fonctionne plus, je n'arrive pas à comprendre pourquoi.

Si quelqu'un a une piste à me donner je suis preneur.

demandé 16-Avr-2015 par DoubleNain (1,718 points)

Qu'est-ce que tu entends par "ca ne fonctionne plus" ?

Avec ton code, j'obtiens le même résultat (seul l'ordre change)

>>> from ipaddr import IPv4Address
>>> reserved = {"formation" : [IPv4Address("192.168.0.1"), IPv4Address("192.168.0.3")], "DR" : [IPv4Address("10.59.6.2"),IPv4Address("10.59.6.3")]}
>>> alls = {"formation" : [IPv4Address("192.168.0.1"), IPv4Address("192.168.0.2"), IPv4Address("192.168.0.3")], "DR" : [IPv4Address("10.59.6.2"), IPv4Address("10.59.6.3"), IPv4Address("10.59.6.4"), IPv4Address("10.59.6.5")]}
>>> free={}
>>>
>>>
>>> for k, v in alls.iteritems():
...     for ki, vi in reserved.iteritems():
...         if k == ki:
...             free[k] = set(v).difference(set(vi))
...
>>> free
{'formation': set([IPv4Address('192.168.0.2')]), 'DR': set([IPv4Address('10.59.6.5'), IPv4Address('10.59.6.4')])}
# {'formation': set(['192.168.0.2']), 'DR': set(['10.59.6.4', '10.59.6.5'])}

En fait, j'obtiens un dico vide. Je vais vérifier mon code j'ai peut-être oublié un import...comme une grosse mirette.

3 Réponses

+3 votes
 
Meilleure réponse

Ca ne répond pas à la question sur pourquoi ça ne marche pas mais voilà encore une autre façon de faire. En fait je suis parti du fait que tu ne compares pas des dictionnaires mais plutôt des listes contenues dans des dictionnaires.

free = {}
for k in alls.keys():
    free[k]=set([x for x in alls[k] if x not in reserved[k]])

(Pas testé avec ipaddr)

répondu 17-Avr-2015 par furankun (1,434 points)
sélectionné 17-Avr-2015 par DoubleNain

J'ai effectivement oublié de faire l'import adéquat comme un gros naze, merci à vous, désolé pour le dérangement ;) c'est cela d'éclater trop son code.

+1 vote

Si j'ai bien compris : Tu peux essayer ça , c'est une façon un peu plus pythonesque de faire les choses et qui tien sur 3 lignes :

diffkeys = [k for k in dict1 if dict1[k] != dict2[k]]
for k in diffkeys:
  print k, ':', dict1[k]

Edit : Je viens de remarquer que mon code ne fonctionne pas sur les dico avec des éléments non-simples, comme les ensembles que tu proposes dans tes dico.

répondu 16-Avr-2015 par boblinux (3,092 points)
edité 16-Avr-2015 par boblinux
+2 votes

Pourquoi ne pas utiliser set comme il faut ?

free = {k: set(v) - set(reserved[k]) for k, v in alls.items()}
répondu 5-Aou-2015 par yoch (2,514 points)
...