Je n'ai pas trouvé de réponse que je cherchais, alors je l'ai trouvée par moi-même et j'aimerais la partager avec vous. Ceux-ci : L'équivalent Python de zip pour les dictionnaires n'implémentent pas la "valeur par défaut" (aka. plus longue saveur) ni ne gardez la commande.

Comment compresser des OrderedDict en python dans la saveur "zip_longest" ?

Ayant:

from collections import OrderedDict

o1 = OrderedDict([("key_a", "a1"), ("key_b", "b1")])
o2 = OrderedDict([("key_a", "a2"), ("key_h", "h2")])
o3 = OrderedDict([("key_c", "c3")])
o4 = OrderedDict([("key_x", "x4")])

Comment obtenir des paires de clés et des valeurs compressées correspondantes de chaque OrderedDict passé, mais avec None si la valeur est manquante ?

expected_result = [
    ('key_a', ('a1', 'a2', None, None)),
    ('key_b', ('b1', None, None, None)),
    ('key_h', (None, 'h2', None, None)),
    ('key_c', (None, None, 'c3', None)),
    ('key_x', (None, None, None, 'x4')),
]
3
Mikaelblomkvistsson 15 mars 2019 à 01:30

2 réponses

Meilleure réponse

Vous pouvez utiliser une compréhension de liste qui itère sur un OrderedDict créé à partir de toutes les clés des dicts donnés et génère des tuples clé-valeur avec des valeurs étant un tuple avec une expression génératrice qui itère à travers les dicts et renvoie la valeur du clé donnée dans chaque dict:

def zip_dicts(*dicts):
    return [(k, tuple(d.get(k) for d in dicts)) for k in OrderedDict.fromkeys(k for d in dicts for k in d)]

De sorte que zip_dicts(o1, o2, o3, o4) renvoie :

[('key_a', ('a1', 'a2', None, None)),
 ('key_b', ('b1', None, None, None)),
 ('key_h', (None, 'h2', None, None)),
 ('key_c', (None, None, 'c3', None)),
 ('key_x', (None, None, None, 'x4'))]
2
blhsing 15 mars 2019 à 19:58

@blhsing a fourni la solution la plus mignonne. Celui-ci est une alternative. Fonctionne en python 2 et 3 :

def zip_ordered_mappings_default(*mappings):
    collected_keys = set()
    for key in (key for mapping in mappings for key in mapping):
        if key not in collected_keys:
            collected_keys.add(key)
            yield key, tuple(collection.get(key) for collection in mappings)

# usage:
assert list(zip_ordered_mappings_default(o1, o2, o3, o4)) == expected_result

L'ordre des éléments résultants est conservé et équivaut à l'union d'ensembles ordonnés créés à partir des clés de dict transmises. C'est à dire. de nouvelles clés apparaissent à la fin.

La solution est assez générale et peut également être utilisée avec des dict classiques :

assert dict(zip_ordered_mappings_default(dict(o1), dict(o2), dict(o3), dict(o4))) == {
    'key_a': ('a1', 'a2', None, None),
    'key_b': ('b1', None, None, None),
    'key_h': (None, 'h2', None, None),
    'key_c': (None, None, 'c3', None),
    'key_x': (None, None, None, 'x4')
}

Bien sûr, dans le cas de dicts, l'ordre des éléments n'est pas conservé, mais les tuples dans les valeurs résultantes reflètent l'ordre des arguments de la fonction.

1
Mikaelblomkvistsson 15 mars 2019 à 21:23