【问题标题】:Zip several dicts or OrderedDict keeping order and giving default value (like zip_longest)压缩几个 dicts 或 OrderedDict 保持顺序并提供默认值(如 zip_longest)
【发布时间】:2019-08-05 23:09:35
【问题描述】:

我没有找到我要找的答案,所以我自己想出来了,想和你分享。这些:Python equivalent of zip for dictionaries 不实现“默认值”(又名最长风味),也不保持顺序。

如何以“zip_longest”风格在 python 中压缩OrderedDicts?

拥有:

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")])

如何从传递的每个 OrderedDict 中获取成对的键和对应的压缩值,但如果缺少值,则使用 None

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')),
]

【问题讨论】:

    标签: python python-3.x python-2.7 dictionary


    【解决方案1】:

    您可以使用列表推导式迭代从给定 dicts 的所有键创建的 OrderedDict 并输出键值元组,其值是具有生成器表达式的元组,该生成器表达式遍历 dicts 并返回每个字典中的给定键:

    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)]
    

    这样zip_dicts(o1, o2, o3, 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'))]
    

    【讨论】:

    • 好的!这绝对是最可爱的答案,但可能不是最快的。 OrderedDict 的构造函数会忽略重复项——这会给出有效的结果,但一个键的查询次数与它在所有输入字典中出现的次数一样多。对于小型收藏,它是最佳选择。
    • 不知道为什么要使用索引来构建元组,而不是:return OrderedDict((k, tuple(d_.get(k) for d_ in dicts)) for d in dicts for k in d)
    • 感谢您的反馈。我已经更新了我的答案,这样它就不再浪费时间通过首先从键生成 OrderedDict 来生成重复的元组。它现在还迭代 dicts 而不是 dicts 长度上的索引(现在看起来确实很明显,但我最初计划使用 index 来获得使用索引的意义,但后来决定不使用它接近并忘记切换回迭代迭代)。
    【解决方案2】:

    @blhsing 提供了最可爱的solution。这是另一种选择。 在 python 2 和 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
    

    结果项的顺序保持不变,相当于从传递的 dict 键创建的有序集的并集。 IE。新键出现在末尾。

    该解决方案非常通用,也可以与常规dicts 一起使用:

    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')
    }
    

    当然,在 dicts 的情况下,项目的顺序不会保留,但结果值中的元组反映了函数参数的顺序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-13
      • 2012-01-29
      • 2016-11-08
      • 1970-01-01
      • 2013-03-21
      • 2014-12-01
      • 2017-05-25
      相关资源
      最近更新 更多