【问题标题】:Efficiently filtering a dictionary in-place有效地就地过滤字典
【发布时间】:2018-02-16 09:51:48
【问题描述】:

我们有一个字典d1 和一个条件cond。我们希望 d1 只包含满足条件cond 的值。一种方法是:

d1 = {k:v for k,v in d1.items() if cond(v)}

但是,这会创建一个新字典,如果 d1 很大,这可能会非常低内存。

另一种选择是:

for k,v in d1.items():
    if not cond(v):
       d1.pop(k)

但是,这会在迭代时修改字典,并生成错误:“RuntimeError: dictionary changed size during iteration”。

在 Python 3 中就地过滤字典的正确方法是什么?

【问题讨论】:

  • 为什么你认为第一种方式效率低? d1.items() 在 py 3 中只创建一个视图,它不会复制字典
  • @Chris_Rands 但是,命令“{k:v for k,v in d1.items() if cond(v)}”不会创建一个新字典,然后将其放入变量“d1”?
  • 我明白了,所以你想最大化内存效率?我会投票重新打开欺骗是关于速度
  • 满足cond(v) 的键集可能很大吗?另外,您希望d1 变得多大?
  • @JoelCornett 我希望传递键的集合有数万个字符串键。我不确定这在 Python 中需要多少内存。

标签: python python-3.x dictionary


【解决方案1】:

如果满足条件的键对应的值不多,那么你可以先聚合键,然后修剪字典:

for k in [k for k,v in d1.items() if cond(v)]:
    del d1[k]

如果列表[k for k,v in d1.items() if cond(v)] 太大,可以“依次”处理字典,即组合键直到它们的计数不超过阈值,修剪字典,然后重复直到没有更多满足条件的键:

from itertools import islice

def prune(d, cond, chunk_size = 1000):
    change = True
    while change:
        change = False

        keys = list(islice((k for k,v in d.items() if cond(v)), chunk_size))
        for k in keys:
            change = True
            del d[k]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-25
    • 1970-01-01
    • 2018-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多