【问题标题】:Sort python list into dictionary of lists, based on property in list根据列表中的属性将 python 列表排序到列表字典中
【发布时间】:2017-02-15 13:57:40
【问题描述】:

我正在尝试通过原始列表中对象的属性将 python 中的对象列表排序到列表字典中

我已经在下面完成了,但这感觉就像我应该能够使用字典理解来做的事情?

for position in totals["positions"]:
        if not hasattr(totals["positions_dict"], position.get_asset_type_display()):
            totals["positions_dict"][position.get_asset_type_display()] = []
        totals["positions_dict"][position.get_asset_type_display()].append(position)

一些自我改进

totals["positions_dict"] = {}
    for position in totals["positions"]:
        key = position.get_asset_type_display()
        if key not in totals["positions_dict"]:
            totals["positions_dict"][key] = []
        totals["positions_dict"][key].append(position)

【问题讨论】:

  • 请发布一些您一直在处理的原始数据以重现您的问题。
  • 似乎更需要collections.defaultdict(list)
  • 不是您问题的答案,但您确定上面的代码有效吗?特别是hasattr?而你调用 position.get_asset_type_display() 三次来存储一个值。通过存储在中间变量中比在这里使用理解更好地提高效率。我认为这是可以做到的,但您最终检索数据的次数会比现在更多。
  • 我认为它可能有一个错误,是的,在那些额外的调用中完全正确。在我知道代码导致瓶颈...并且可以正常工作之前,我通常会避免进行最小的优化!

标签: python list dictionary dictionary-comprehension


【解决方案1】:

您可以在字典理解中使用 itertools.groupbyoperator.methodcaller

from operator import methodcaller
from itertools import groupby

key = methodcaller('get_asset_type_display')
totals["positions_dict"] = {k: list(g) for k, g in groupby(sorted(totals["positions"], key=key), key=key)}

按照@Jean-FrançoisFabre 的建议,使用defaultdict 可以让您在一个循环中通过一次调用get_asset_type_display() 来做到这一点:

from collections import defaultdict

totals["positions_dict"] = defaultdict(list)
for position in totals["positions"]:
    totals["positions_dict"][position.get_asset_type_display()].append(position)

【讨论】:

  • 就“更加pythonic”而言,您的版本会“胜出”吗?还是一种风格选择?
  • 除了废话重复调用关键方法。
  • 对于您的答案,键需要来自列表中项目的属性,即“asset_type”。所以不应该调用在函数之外获取密钥。
  • 好吧,这是否是最好的或最高效的解决方案,取决于get_asset_type_display 调用的成本。如果这很昂贵,那么创建一个中间数据结构来存储每个位置的asset_type 是有意义的。
【解决方案2】:

尚未对此进行测试,因为我没有您的数据。 而且我认为它相当丑陋,但它可能会起作用:

totals ['positions_dict'] = {
    key: [
        position
        for position in totals ['positions']
        if position.get_asset_type_display () == key
    ]
    for key in {
        position.get_asset_type_display ()
        for position in totals ['positions']
    }
}

但我更喜欢一些非常简单的东西,并避免不必要的查找/调用:

positions = totals ['positions']
positions_dict = {}

for position in positions:
    key = position.get_asset_type_display ()
    if key in positions_dict:
        positions_dict [key] .append (position)
    else:
        positions_dict [key] = [position]


totals ['positions_dict'] = positions_dict
positions = totals ['positions']

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-19
    • 2018-01-10
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多