繁体   English   中英

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

[英]how to remove an item from a dictionary that is iterated?

我有一本带时间戳的字典,我想遍历它并删除那些被认为过时的项目(在Python中)我该如何最好地解决呢? 这段代码给了我RuntimeError:字典在迭代过程中改变了大小

    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

在迭代集合时,您不能修改它们。

有几种解决方法:

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

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

这是其他两个的实现:

new_img_dict = {}
for key in img_dict:
    if (time.time()-float(img_dict[key])) >= stale_img:
        logger.debug('STALE IMAGE FROM '+hexlify(key)+ ' - GOT CLOSED NOW!')
        data_upload = True
   else:
       new_img_dict[key] = img_dict[key]
img_dict = new_img_dict

要么:

for key in img_dict.keys():
    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

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

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

通常,第一个通常更容易推论-通常,不可变的对象和纯操作很容易推论。 例如,如果在某处引发异常,则img_dict将始终具有原始版本或完整版本,而不会介于两者之间。 当然,您不必在迭代过程中仔细考虑更改内容的含义。 但是,在极少数情况下,很难将“在foo处删除所有内容”算法转换为“在foo处删除所有内容”算法。

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

为了提高性能,如果您要过滤掉许多值,则第一个通常会更快,并且使用更少的内存,而如果保留大多数值,第二个通常会更好。 (对于不同的收集类型,临界值是不同的。通常,它并不重要,如果确实如此,则应同时编写方式和配置文件。)

回到#0,我认为这可能适用于这种情况。 您正在浏览所有键以查看是否有旧键,将其删除。 例如,如果您使用了排序列表或优先级队列,则无需这样做。 现在,如果您需要使用集合作为dict次数多于刷新旧值的次数,那么更改数据结构所带来的成本可能比收益还多。 但是为什么没有两者呢? 如果您有一个排序的键列表,那么在字典将键映射到值的顶部,则可以这样做:

for key in img_sorted_key_list:
    if time.time() - float(key) > stale_img:
        break
    del img_dict[key]

或者,更简单地说:

stale_time = time.time() - stale_img
for key in itertools.takewhile(lambda key: float(key) < stale_time, 
                               img_sorted_key_list):
    del img_dict[key]

您可以将排序后的键列表和字典一起包装到一个不错的Cache类中。

看这个例子。 也许会有所帮助。 请记住,删除列表或字典中的元素时要从头开始。 避免使用iteritems()方法。

keysMap = [
      {"key": 1 },
      {"key" : 2 },
      {"key" : 3 },
      {"key" : 4 },
      {"key" : 5 },
      {"key" : 6 }
       ]   
i=len(keysMap)-1
while i > 0 :
    key = keysMap[i]
    if key["key"]==2 :
        del(keysMap[i])
    i=i-1

# Printing the object data after deleting element key=2    
while i < len(keysMap) :
    key = keysMap[i]
    print key
    i=i+1 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM