【问题标题】:Efficient liner for switching list of dicts to dictionary of lists [duplicate]用于将字典列表切换到列表字典的高效衬垫[重复]
【发布时间】:2020-12-14 15:40:22
【问题描述】:

我发现自己经常重复以下代码(或类似代码):

users = {}
for d in data:
    if d['user'] in users.keys():
        users[d['user']].append(d)
    else:
        users[d['user']] = [d]

在这里,data 是一个字典列表,我想将列表拆分为较小的列表,映射到它们的 d["user"] 值作为字典中的键。

我想要一种在一行中执行此操作的方法,因为这些多行让我很烦。

然而,我能想到的唯一方法是将我的 O(N) 算法(上图)更改为 O(N^2) 算法,例如:

users = {d["user"]: [d for d in data if d["user"] == u] for d in data}

显然,这种低效率是不可接受的......

【问题讨论】:

  • 您可以使用 defaultdict 而不是字典,这样可以节省 if。除此之外,没有高性能(和可读)的方法来做到这一点。另一种方法是排序和分组,优于 O(n^2) 但不是 O(n)

标签: python list performance dictionary one-liner


【解决方案1】:

您可以使用这种语法进行测试

[3*n+1 if n%2==1 else n//2 for n in range(100)]

最适合您的需求,尤其是处理理解列表等。为了您的目的,应该这样做:

users = {users[d['user']].append(d) if d['user'] in users else users[d['user']] = [d] for d in data}

【讨论】:

  • 你能在这样的单行字典构造器中检查if d['user'] in users吗?我不认为你能做到这一点..?
【解决方案2】:

这与您在原始评论中发布的内容或多或少相同,但更简洁:

# set up sample data
from random import randint, choice
names = ["Alice", "Bob", "Charlie"]
data = [{"user": choice(names), "value": randint(1, 10)} for _ in range(10)]

# convert data to dict of columns
users = {}
for d in data:
    users.setdefault(d["user"], []).append(d)

如果您的数据已经排序,您可以执行以下操作

from operator import itemgetter
from itertools import groupby

# assume sorted data
data = sorted(data, key=itemgetter("user"))

{k: list(g) for k, g in itertools.groupby(data, key=itemgetter("user"))}

【讨论】:

    【解决方案3】:

    你可以把它变成一个怪物的班轮,像这样:

    users = { u:v[u] for v in [dict()] for d in data for u in [d['user']] if not v.setdefault(u,[]).append(d) }
    

    或者将其缩减为两行,如下所示:

    users = dict()
    for d in data: users.setdefault(d['user'],[]).append(d)
    

    两者都将在 O(N) 时间内运行(但我个人更喜欢第二个)

    您可以做的另一件事是创建一个函数并使用它来代替:

    def dataToDict(data,key):
        result = dict()
        for d in data: result.setdefault(d[key],[]).append(d)
        return result
    
    users = dataToDict(data,"user")
    

    【讨论】:

      猜你喜欢
      • 2017-07-05
      • 1970-01-01
      • 1970-01-01
      • 2019-11-27
      • 2020-03-19
      • 2016-08-29
      • 1970-01-01
      • 2017-04-23
      • 2021-10-13
      相关资源
      最近更新 更多