在Python中从dict中删除某些键的最快方法

Har*_*ons 8 python dictionary filter

我正在寻找删除python dict中某些键的最快/最有效的方法

这里有一些选择

for k in somedict.keys(): 
    if k.startswith("someprefix"): 
        del somedict[k]
Run Code Online (Sandbox Code Playgroud)

要么

dict((k, v) for (k, v) in somedict.iteritems() if not k.startswith('someprefix'))
Run Code Online (Sandbox Code Playgroud)

逻辑上第一个片段在较小的dicts上应该更快,它不会创建dict的副本但会创建所有键的列表,但是双重查找和dict重建是耗时的.虽然第二个在更大的dicts上更快,但需要2倍的内存.我在一些小基准测试中检查了我的假设.

什么更快?

ber*_*nie 13

不仅del更容易理解,而且似乎比pop()稍快:

$ python -m timeit -s "d = {'f':1,'foo':2,'bar':3}" "for k in d.keys():" "  if k.startswith('f'):" "    del d[k]"
1000000 loops, best of 3: 0.733 usec per loop

$ python -m timeit -s "d = {'f':1,'foo':2,'bar':3}" "for k in d.keys():" "  if k.startswith('f'):" "    d.pop(k)"
1000000 loops, best of 3: 0.742 usec per loop
Run Code Online (Sandbox Code Playgroud)

编辑:感谢Alex Martelli提供有关如何进行此基准测试的说明.希望我没有在任何地方滑倒.

首先测量复制所需的时间:

$ python -m timeit -s "d = {'f':1,'foo':2,'bar':3}" "d1 = d.copy()"
1000000 loops, best of 3: 0.278 usec per loop
Run Code Online (Sandbox Code Playgroud)

复制词典的基准:

$ python -m timeit -s "d = {'f':1,'foo':2,'bar':3}" "d1 = d.copy()" "for k in d1.keys():" "  if k.startswith('f'):" "    del d1[k]"
100000 loops, best of 3: 1.95 usec per loop

$ python -m timeit -s "d = {'f':1,'foo':2,'bar':3}" "d1 = d.copy()" "for k in d1.keys():" "  if k.startswith('f'):" "    d1.pop(k)"
100000 loops, best of 3: 2.15 usec per loop
Run Code Online (Sandbox Code Playgroud)

减去复制成本,得到1.872 usec for pop()和1.672 for del.

  • @Adam,使用`timeit`的方法非常错误:在那些1000000循环中,999999在一个单项dict上运行,其中`bar`是唯一的键(`-s`设置代码在每个循环之前不重复).你需要制作和改变一个`d1 = d.copy()`(这个语句是由`timeit`测量的代码的一部分) - 当你测量改变数据的代码时,这种事情是至关重要的.您可以通过将这样的副本添加到您正在计时的所有变体中来标准化(以查找时序比率),单独测量**只是"副本",并从您正在考虑的代码变体的时间中减去它的时间. (4认同)

Ign*_*ams 9

如果dict足够大,那么生成一个全新的dict可能是有意义的.

dict((k, v) for (k, v) in somedict.iteritems() if not k.startswith('someprefix'))
Run Code Online (Sandbox Code Playgroud)