【问题标题】:Combining lists of dictionaries based on list index基于列表索引组合字典列表
【发布时间】:2018-02-01 23:23:20
【问题描述】:

我觉得这个问题之前一定有人问过,但在 Stack Overflow 上找不到。

有没有办法根据列表索引优雅地组合多个字典列表?见下文:

list_1 = [{'hello': 'world'}, {'foo': 'test'}]
list_2 = [{'a': 'b'}, {'c': 'd'}]
result = [{'hello': 'world', 'a': 'b'},
          {'foo': 'test', 'c': 'd'}]

我知道我可以在技术上使用 for 循环,例如:

list_3 = []
for i in range(len(list_1)):
    list_3.append({**list_1[i],**list_2[i]})

有没有办法通过列表理解来做到这一点? 另外,如果我涉及的列表超过 2 个或不知道字典列表的数量怎么办?

【问题讨论】:

  • “我知道我可以在技术上使用 for 循环,例如 for i in range(0,len(list_1) 但是有没有办法通过列表理解来做到这一点?” 的动机是什么这个问题?无法保证列表组合会更快,并且您在for 循环方法中没有表现出任何努力。
  • 很公平,我上面有我的例子

标签: python list dictionary


【解决方案1】:

这会做你想做的事:

result = [{**x, **y} for x, y in zip(list_1, list_2)]

# [{'a': 'b', 'hello': 'world'}, {'c': 'd', 'foo': 'test'}]

请参阅PEP 448 了解** 语法的说明。

对于通用解决方案:

list_1=[{'hello':'world'},{'foo':'test'}]
list_2=[{'a':'b'},{'c':'d'}]
list_3=[{'e':'f'},{'g':'h'}]

lists = [list_1, list_2, list_3]

def merge_dicts(*dict_args):
    result = {}
    for dictionary in dict_args:
        result.update(dictionary)
    return result

result = [merge_dicts(*i) for i in zip(*lists)]

# [{'a': 'b', 'e': 'f', 'hello': 'world'}, {'c': 'd', 'foo': 'test', 'g': 'h'}]

【讨论】:

    【解决方案2】:

    对于通用解决方案,在 Python 3 中,您可以执行以下操作:

    In [14]: from operator import or_
    
    In [15]: from functools import reduce
    
    In [16]: list_of_lists = [list_1, list_2]
    
    In [17]: [dict(reduce(or_, map(dict.items, ds))) for ds in zip(*list_of_lists)]
    Out[17]: [{'a': 'b', 'hello': 'world'}, {'c': 'd', 'foo': 'test'}]
    

    在 Python 2 中,无需导入 reduce,因为它已经在全局命名空间中,但您需要使用 dict.viewitems 而不是 dict.items:

    [dict(reduce(or_, map(dict.viewitems, ds))) for ds in zip(*list_of_lists)]
    

    请注意,我可以看到您的解决方案的唯一真正问题是它使用了for i in range(...),而您应该只遍历zippped 列表。

    【讨论】:

    • 来自问题中的for 循环:1.02 µs ± 2.36 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)。这个答案:3.32 µs ± 55.8 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)。但是,另一个答案中的列表组合确实加快了速度:933 ns ± 15.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)。这是 3.6 顺便说一句。
    • 是的,合并dicts 的最快方法是使用带有update 的forloop。使用reduce(or_, map(dict.viewkeys)) 会更慢,因为有一个创建视图的中间步骤,然后将视图转换为字典。
    • 对不起,我过早地按了进入。我发布了与我最初评论相关的统计数据;列表组合不一定更快。
    • @roganjosh 一种替代方案,它保持通用性但性能更高(尽管开销很大,因此如果 dict 对象很小,则可能不值得):dict(chain.from_iterable(map(dict.items, ds)))
    • 这是一个公平的观点,我的时间是非常小的样本。我可能还不够清醒,无法为更大的样本构建完整的测试用例;如果 OP 关心速度,那么问题应该包含更合理的测试用例 IMO。
    猜你喜欢
    • 2021-06-25
    • 2021-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-22
    相关资源
    最近更新 更多