如何从迭代的字典中删除项目?

std*_*err 0 python dictionary loops

我有一本带有时间戳的字典,我想迭代它并删除被认为过时的项目(在Python中)我该如何最好地解决这个问题?这段代码给了我RuntimeError:dictionarychanged size during iteration

    for key, value in img_dict.iteritems() :
        if (time.time()-float(img_dict[key])) >= stale_img:
            logger.debug('STALE IMAGE FROM '+hexlify(key)+ ' - GOT CLOSED NOW!')
            del img_dict[key]
            data_upload = True
Run Code Online (Sandbox Code Playgroud)

aba*_*ert 5

您无法在迭代集合时修改集合。

\n\n

有几种方法可以解决这个问题:

\n\n
    \n
  • (0) 重新思考你的设计,看看是否需要这样做。
  • \n
  • (1)不要修改集合;相反,构建一个新的、经过过滤的集合。
  • \n
  • (2) 不要迭代集合;相反,迭代集合的副本
  • \n
  • (2.5) 对于字典,迭代键的副本,并显式获取值。
  • \n
\n\n

请注意,尽管迭代了项目,但您已经显式获取了值,因此没有理由在此处使用#2。

\n\n

以下是其他两个的实现:

\n\n
new_img_dict = {}\nfor key in img_dict:\n    if (time.time()-float(img_dict[key])) >= stale_img:\n        logger.debug(\'STALE IMAGE FROM \'+hexlify(key)+ \' - GOT CLOSED NOW!\')\n        data_upload = True\n   else:\n       new_img_dict[key] = img_dict[key]\nimg_dict = new_img_dict\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者:

\n\n
for key in img_dict.keys():\n    if (time.time()-float(img_dict[key])) >= stale_img:\n        logger.debug(\'STALE IMAGE FROM \'+hexlify(key)+ \' - GOT CLOSED NOW!\')\n        del img_dict[key]\n        data_upload = True\n
Run Code Online (Sandbox Code Playgroud)\n\n

(如果您希望它与 Python 3 兼容,请img_dict.keys()执行而不是img_dict.keys()[:]。)

\n\n

那么,您如何在两者之间进行选择呢?

\n\n

第一个通常更容易推理\xe2\x80\x94一般来说,不可变对象和纯操作很容易推理。例如,如果您在某处抛出异常,img_dict则始终会得到原始版本或完成的版本,而不是中间的版本。当然,您不必在迭代某些内容时考虑更改它意味着什么。然而,在某些罕见的情况下,很难将“删除 foo 处的所有内容”算法转换为“复制不是 foo 处的所有内容”算法。

\n\n

第一个通常也更容易重写为推导式(或调用高阶函数,如filter)、变成生成器、重构以提取单独的函数等。

\n\n

就性能而言,如果您要过滤掉许多值,第一个通常会更快并且使用更少的内存,而如果您保留大多数值,第二个通常会更好。(对于不同的集合类型,截止值是不同的。通常,它很少重要,如果重要,您应该以两种方式和配置文件来编写它。)

\n\n

回到#0,我认为它可能适用于这种情况。您正在检查所有钥匙,看看是否有太旧的钥匙,然后将其取下。如果您使用排序列表或优先级队列,则不必这样做。现在,如果您需要更频繁地使用集合而dict不是刷新旧值,那么更改数据结构可能会带来更多的成本而不是收益。但为什么不两者兼得呢?如果您有一个排序的键列表,在将键映射到值的字典之上,那么您可以这样做:

\n\n
for key in img_sorted_key_list:\n    if time.time() - float(key) > stale_img:\n        break\n    del img_dict[key]\n
Run Code Online (Sandbox Code Playgroud)\n\n

或者,更简单地说:

\n\n
stale_time = time.time() - stale_img\nfor key in itertools.takewhile(lambda key: float(key) < stale_time, \n                               img_sorted_key_list):\n    del img_dict[key]\n
Run Code Online (Sandbox Code Playgroud)\n\n

您可以将排序后的键列表和字典包装在一起,形成一个很好的Cache类或其他东西。

\n