1
votes

Itérer en O (n ^ 2/2) un dict

Étant donné un dictionnaire:

res = []
t = [0, 1, 2]

for i in range(len(t):
    for j in range(i):
        res.append(t[i] * t[j])

Je voudrais créer un nouveau dictionnaire qui calcule le produit des valeurs de d et d .

Voici le résultat dont j'ai besoin:

d = {'a#a': 0, 'a#b': 0, 'a#c': 0, 'b#a' : 0, 'b#b' : 1, 'b#c': 2, 'c#a': 0, 'c#b': 2, 'c#c': 4}

Cependant je ne veux pas avoir ce résultat:

d = {'a#a': 0, 'a#b': 0, 'a#c': 0, 'b#b' : 1, 'b#c': 2, 'c#c': 4}


0 commentaires

5 Réponses :


1
votes

Vous pouvez utiliser une compréhension de dict pour ceci:

d = {'b': 0, 'a': 1, 'c': 2}
dd = {f'{k}#{l}': v*w 
      for i,(k,v) in enumerate(d.items()) 
      for j,(l,w) in enumerate(d.items()) 
      if i<=j}
>>> {'b#b': 0, 'b#a': 0, 'b#c': 0, 'a#a': 1, 'a#c': 2, 'c#c': 4}

EDIT: Si vous voulez que le résultat soit trié par apparition d'objet dans d:

dd = {f'{k}#{l}': v*w for k,v in d.items() for l,w in d.items() if k<=l}
>>> {'a#a': 0, 'a#b': 0, 'a#c': 0, 'b#b': 1, 'b#c': 2, 'c#c': 4}


3 commentaires

Cela ne fonctionne pas si la clé 'a' vient après 'b' .


Que veux-tu dire ? Cela fonctionne parfaitement pour moi même si a vient après b


Je veux dire que vous ne verrez pas 'b # a' dans le dictionnaire de sortie, si dans l'entrée 'a' vient après 'b' parce que la condition échoue.



0
votes

Pourquoi ne pas utiliser une compréhension de dictionnaire ?

result = {}
for k1 in d:
    for k2 in (k for k in d if k >= k1):
        result[f"{k1}#{k2}"] = d[k1] * d[k2]


2 commentaires

Comme @Austin le note dans une autre réponse, ces deux éléments ne respecteront pas le tri original des clés, donc a # b remplacera b # a même si b a été inséré avant a .


@Acorn L'OP n'a probablement pas besoin de garder l'ordre, il veut juste que chaque paire de clés différentes soit dans le résultat une seule fois (c'est-à-dire soit a # b soit b # a mais pas les deux).



3
votes

Python est livré avec des piles, mais le moyen le plus propre n'est pas toujours évident. Vous avez déjà la fonction que vous souhaitez intégrer dans itertools .

Essayez ceci:

>>> print(result)
{'a#a': 0, 'a#b': 0, 'a#c': 0, 'b#b': 1, 'b#c': 2, 'c#c': 4}

itertools.combinations vous donne toutes les paires sans duplication, itertools.combinations_with_replacement vous donne les paires uniques, y compris celles où les clés sont les mêmes.

Sortie:

import itertools
result = {f'{k1}#{k2}': d[k1]*d[k2]
   for k1, k2 in itertools.combinations_with_replacement(d, 2)}


0 commentaires

-1
votes

itertools pour le plaisir:

{'a#a': 0, 'a#b': 0, 'a#c': 0, 'b#b': 1, 'b#c': 2, 'c#c': 4}

Sortie:

from itertools import combinations_with_replacement

letter_pairs, number_pairs = (combinations_with_replacement(l, r=2) for l in zip(*d.items()))
result = {letters: number 
          for letters, number in zip(map('#'.join, letter_pairs), 
                                     (a * b for a, b in number_pairs))}

print(result)


0 commentaires

0
votes

Vous pouvez utiliser itertools pour obtenir les combinaisons et former le dictionnaire!

>>> from itertools import combinations_with_replacement
>>> {"{}#{}".format(v1,v2): d[v1]*d[v2] for v1,v2 in combinations_with_replacement(d.keys(),2)}
{'a#c': 0, 'a#b': 0, 'a#a': 0, 'b#b': 1, 'c#c': 4, 'c#b': 2}

Ou aussi simple que pointé par Duncan,

>>> from itertools import combinations
>>>
>>> d
{'a': 0, 'c': 2, 'b': 1}
>>> combinations(d.keys(),2) # this returns an iterator
<itertools.combinations object at 0x1065dc100>
>>> list(combinations(d.keys(),2)) # on converting them to a list 
[('a', 'c'), ('a', 'b'), ('c', 'b')]
>>> {"{}#{}".format(v1,v2): (v1,v2) for v1,v2 in combinations(d.keys(),2)} # form a dict using dict comprehension, with "a#a" as key and a tuple of two values.
{'a#c': ('a', 'c'), 'a#b': ('a', 'b'), 'c#b': ('c', 'b')}
>>> {"{}#{}".format(v1,v2): d[v1]*d[v2] for v1,v2 in combinations(d.keys(),2)}
{'a#c': 0, 'a#b': 0, 'c#b': 2} # form the actual dict with product as values
>>> {"{}#{}".format(v1,v2):d[v1]*d[v2] for v1,v2 in list(combinations(d.keys(),2)) + [(v1,v1) for v1 in d.keys()]} # form the dict including the self products!
{'a#c': 0, 'a#b': 0, 'a#a': 0, 'b#b': 1, 'c#c': 4, 'c#b': 2}

p >


0 commentaires