custom dict that allows delete during iteration

后端 未结 7 1968
时光说笑
时光说笑 2020-12-08 09:53

UPDATED based on Lennart Regebro\'s answer

Suppose you iterate through a dictionary, and sometimes need to delete an element. The following is very efficient:

<
7条回答
  •  眼角桃花
    2020-12-08 10:34

    What you need to do is to not modify the list of keys you iterating over. You can do this in three ways:

    1. Make a copy of the keys in a separate list and iterate over that. You can then safely delete the keys in the dictionary during iteration. This is the easiest, and fastest, unless the dictionary is huge in which case you should start thinking about using a database in any case. Code:

      for k in list(dict_):
        if condition(k, dict_[k]):
          del dict_[k]
          continue
        # do other things you need to do in this loop
      
    2. Make a copy not of the keys you are iterating over, but a copy of the keys you are to delete. In other words, don't delete these keys while iterating instead add them to a list, then delete the keys in that list once you are finished iterating. This is slightly more complicated than 1. but much less than 3. It is also fast. This is what you do in your first example.

      delete_these = []
      for k in dict_:
        if condition(k, dict_[k]):
          delete_these.append(k)
          continue
        # do other things you need to do in this loop
      
      for k in delete_these:
          del dict_[k]
      
    3. The only way to avoid making some sort of new list is, as you suggest, to make a special dictionary. But that requires when you delete keys it does not actually delete the keys, but only mark them as deleted, and then delete them for real only once you call a purge method. This requires quite a lot of implementation and there are edge-cases and you'll fudge yourself by forgetting to purge, etc. And iterating over the dictionary must still include the deleted keys, which will bite you at some point. So I wouldn't recommend this. Also, however you implement this in Python, you are likely to just once again end up with a list of things to delete, so it's likely to just be a complicated and error prone version of 2. If you implement it in C, you could probably get away with the copying by adding the flags directly into the hash-key structure. But as mentioned, the problems really overshadow the benefits.

提交回复
热议问题