【问题标题】:create optimum data structure python创建最佳数据结构python
【发布时间】:2015-04-24 18:54:38
【问题描述】:

我正在交叉引用共享 6 个公共字段的两个数据源。这个想法是文件 1 中的营销成本被分配到文件 2 中的销售交易中。我已经编写了一种从第一个文件构建数据结构的方法,以便第二个文件可以快速访问它,但它似乎没有-对我来说是pythonic。我有兴趣就是否有人认为可以以更好的方式编写它获得一些意见和意见。

cost_matrix = {}
for line in marketing_costs:
    line_date_object = time.strptime(line['date'], "%d/%m/%Y")
    period = '%04d_%02d' % (line_date_object.tm_year, line_date_object.tm_mon)
    territory = line['territory'].lower()
    salesperson=line['salesperson'].lower()
    customer_type = line['customer_type'].lower()
    affiliate=line['affiliate'].lower()
    product_group = line['product_group'].lower()
    line_mktg_cost=line['mktg_cost']
    try:
        cost_matrix[period]
    except KeyError:
        cost_matrix[period]={}
    try:
        cost_matrix[period][territory]
    except KeyError:
        cost_matrix[period][territory]={}
    try:
        cost_matrix[period][territory][salesperson]
    except KeyError:
        cost_matrix[period][territory][salesperson]={}
    try:
        cost_matrix[period][territory][salesperson][customer_type]
    except KeyError:
        cost_matrix[period][territory][salesperson][customer_type]={}
    try:
        cost_matrix[period][territory][salesperson][customer_type][affiliate]
    except KeyError:
        cost_matrix[period][territory][salesperson][customer_type][affiliate]={}
    try:
        cost_matrix[period][territory][salesperson][customer_type][affiliate][product_group]
    except KeyError:
        cost_matrix[period][territory][salesperson][customer_type][affiliate][product_group]={}
        cost_matrix[period][territory][salesperson][customer_type][affiliate][product_group]['mktg_cost']=0
    cost_matrix[period][territory][salesperson][customer_type][affiliate][product_group]['mktg_cost']+=Decimal(line_mktg_cost)

【问题讨论】:

    标签: python dictionary data-structures


    【解决方案1】:

    这些 4 行 try/except 块中的每一个都可以使用 setdefault 替换为 1 行:

    setdefault(key[, default])

    • 如果 key 在字典中,则返回其值。如果不是,则插入 key,其值为 default 并返回 default默认默认为None

    所以这个:

    cost_matrix[period].setdefault(territory, {})
    

    …等价于:

    try:
        cost_matrix[period][territory]
    except KeyError:
        cost_matrix[period][territory]={}
    

    除了您可以在更大的表达式中使用它,这意味着理论上您可以根据需要将整个内容变成一个巨大的表达式,尽管我不确定我是否会这样做。


    您可以使用递归defaultdict 进一步简化事情。 defaultdict 基本上只是一个dict,它通过自动设置默认值来处理丢失的键,而递归的则使用另一个defaultdict 而不是普通的dict。 (你仍然需要一个 setdefault 或者只是在末尾分配简单的键来处理 0 的默认值,而不是另一个字典......)

    像这样:

    _make_defaultdict = lambda: defaultdict(_make_defaultdict)
    recursive_defaultdict = defaultdict(_make_defaultdict)
    
    cost_matrix = recursive_defaultdict()
    cost_matrix[period][territory][salesperson][customer_type][
        affiliate][product_group]['mktg_cost'] = 0
    cost_matrix[period][territory][salesperson][customer_type][
        affiliate][product_group]['mktg_cost'] += Decimal(line_mktg_cost)
    

    但是,请注意,这意味着您永远不会在代码中的其他任何地方获得KeyError。如果这不可接受,请坚持使用setdefault。 (虽然如果你基本上是在构建字典,然后使用它,你可以通过递归复制它来将它“冻结”成普通的dict……)

    【讨论】:

    • @TimPietzcker:感谢您发现并修正错字。
    • 谢谢你,太好了!我将使用 setdefault,因为脚本的其他部分依赖于 KeyError 异常。
    • @TommyGaboreau:ActiveState 上还有一个用于递归 defaultdict 的配方,如果您想搜索它,您可以即时冻结和解冻。 (我使用它一次只是因为它是一个很好的想法,但我再也没有在实际代码中使用过它,因为我从来没有很好地使用它......但也许你会。)
    • 很高兴知道这样的事情存在,但现在您的 setdefault 解决方案是完美的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-02
    • 1970-01-01
    • 1970-01-01
    • 2017-09-26
    • 1970-01-01
    相关资源
    最近更新 更多