【问题标题】:How to write dictionary comprehension in this complicated case?在这种复杂的情况下如何编写字典理解?
【发布时间】:2023-04-02 18:20:01
【问题描述】:

一个例子是人为的,但我多次遇到类似的问题。

db_file_names = ['f1', 'f2']  # list of database files

def make_report(filename):
    # read the database and prepare some report object
    return report_object

现在我要构造一个字典:db_version -> number_of_tables。报告对象包含我需要的所有信息。

字典理解可能如下所示:

d = {
    make_report(filename).db_version: make_report(filename).num_tables
    for filename in db_file_names
}

这种方法有时有效,但效率很低:为每个数据库准备两次报告。

为了避免这种低效率,我通常使用以下方法之一:

使用临时存储:

reports = [make_report(filename) for filename in db_file_names]
d = {r.db_version: r.num_tables for r in reports}

或者使用一些适配器生成器:

def gen_data():
    for filename in db_file_names:
        report = make_report(filename)
        yield report.db_version, report.num_tables

d = {dat[0]: dat[1] for dat in gen_data()}

但通常只有在我写了一些错误的理解之后,思考并意识到,在这种情况下,干净简单的理解是不可能的。

问题是,在这种情况下,有没有更好的方法来创建所需的字典?

从昨天开始(当我决定发布这个问题时)我发明了另一种方法,我比其他所有方法都更喜欢:

d = {
    report.db_version: report.num_tables
    for filename in db_file_names
    for report in [make_report(filename), ]
}

但即使是这个看起来也不是很好。

【问题讨论】:

    标签: python dictionary list-comprehension dictionary-comprehension


    【解决方案1】:

    你可以使用:

    d = {
        r.db_version: r.num_tables
        for r in map(make_report, db_file_names)
    }
    

    请注意,在 Python 3 中,map 提供了一个迭代器,因此没有不必要的存储成本。

    【讨论】:

      【解决方案2】:

      这是一个函数式的方法:

      from operator import attrgetter
      
      res = dict(map(attrgetter('db_version', 'num_tables'),
                     map(make_report, db_file_names)))
      

      很遗憾,功能组合不是标准库的一部分,但第 3 方 toolz 确实提供了此功能:

      from toolz import compose
      
      foo = compose(attrgetter('db_version', 'num_tables'), make_report)
      res = dict(map(foo, db_file_names))
      

      从概念上讲,您可以认为这些函数式解决方案输出一个可迭代的元组,然后可以直接将其馈送到dict

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-11-30
        • 2021-05-21
        • 2013-11-03
        • 2012-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多