3
votes

Conseils pour un code plus élégant pour créer un dictionnaire

Je crée un dictionnaire avec des clés et des valeurs à partir de listes:

dictionary = {'Ptot': 'max', 'P1': 'first', 'P2': 'first', 'P3': 'first', 'Q1': 'first', 'Q2': 'first', 'Q3': 'first'}

Je peux créer manuellement le dictionnaire comme suit:

keys = ['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3']
val = ['max', 'first', 'first', 'first', 'first', 'first', 'first']

Comment puis-je créer plus élégamment le dict à partir des listes par une boucle for? Mon problème est que la taille des listes est beaucoup plus grande que cet exemple.


2 commentaires

ont-ils toujours la même taille?


d = {} pour k, v dans zip (clés, val): d [k] = v


3 Réponses :


6
votes

Utilisez une compréhension de dictionnaire, où vous choisissez votre clé et votre valeur à partir des listes clés et val lorsque vous les parcourez, et juste pour être sûr si le les clés et val sont de longueurs inégales, vous pouvez les compresser toutes ensemble via itertools.zip_longest , qui créera un itérateur de la sous-séquence la plus longue, en s'assurant que dire clés est plus long que val , nous n'avons aucune clé pour eux, peut-être pour les réattribuer à l'avenir (Merci @quamrana)

from itertools import zip_longest
keys = ['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3', 'QX', 'QY']
val = ['max', 'first', 'first', 'first', 'first', 'first', 'first']

#Pick the smaller of the 2 lengths and iterate only on those indexes
length = min(len(keys), len(val))
print({keys[idx]:val[idx] for idx in range(length)})

La sortie est

{'Ptot': 'max', 'P1': 'first', 'P2': 'first', 
'P3': 'first', 'Q1': 'first', 'Q2': 'first', 'Q3': 'first', 
'QX': None, 'QY': None}

Un exemple de plus grande longueur de clés puis val

from itertools import zip_longest
keys = ['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3', 'QX', 'QY']
val = ['max', 'first', 'first', 'first', 'first', 'first', 'first']

print({k:v for k,v in zip_longest(keys, val)})

La sortie sera

{'Ptot': 'max', 'P1': 'first', 'P2': 'first', 'P3': 'first', 'Q1': 'first', 'Q2': 'first', 'Q3': 'first'}

donc nous voyons que les clés ne sont pas perdues ici, mais sont utilisées et les valeurs définies sur None, mais en utilisant zip causera u s de perdre ces clés!

Mais au cas où nous ne voudrions choisir que des éléments de la plus petite liste, nous pouvons faire comme suit (merci @MitchelPaulin)

from itertools import zip_longest
keys = ['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3']
val = ['max', 'first', 'first', 'first', 'first', 'first', 'first']

print({k:v for k,v in zip_longest(keys, val)})


3 commentaires

Vous voudrez peut-être utiliser min (len (clés), len (val)) juste pour être sûr


Cela ne fonctionnera que si les deux clés et val contiennent le même nombre d'éléments


Vous pouvez zip les clés et vals ensemble.



11
votes

Jetez un œil à zip :

>>> d = dict(zip(keys, val))
>>> d
{'Ptot': 'max', 'P1': 'first', 'P2': 'first', 'P3': 'first', 'Q1': 'first', 'Q2': 'first', 'Q3': 'first'}

Créez un itérateur qui regroupe les éléments de chacun des itérables.

Renvoie un itérateur de tuples, où le i-ème tuple contient le i-ème élément de chacune des séquences d'arguments ou des itérables.

Ensuite, nous passons la valeur de retour à dict pour créer un dictionnaire. C'est probablement plus efficace qu'une simple boucle car les composants intégrés fonctionnent à la vitesse C dans Python et les implémenteurs ont probablement eu plus de temps pour l'optimiser.


0 commentaires

0
votes

Cette approche utilise zip avec un simple ajout de la deuxième liste pour correspondre aux tailles.

{'Ptot': 'max', 'P1': 'first', 'P2': None, 'P3': None, 'Q1': None, 'Q2': None, 'Q3': None, 'Q4': None}

Notez que j'ai utilisé append (None) code> comme zip_longest utilise fillvalue = None .


l1=['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3', 'Q4' ]
l2=['max', 'first' ]

# make sure we have the same length
for i in range (len(l1)-len(l2)): l2.append(None)

d={}
d={k:v for k,v in zip(l1,l2)}
print(d)


0 commentaires