Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #7974

Re: How to iterate on a changing dictionary

From Roy Smith <roy@panix.com>
Newsgroups comp.lang.python
Subject Re: How to iterate on a changing dictionary
Date 2011-06-19 11:53 -0400
Organization PANIX Public Access Internet and UNIX, NYC
Message-ID <roy-3DDD62.11534419062011@news.panix.com> (permalink)
References <itl1a5$rom$1@speranza.aioe.org> <mailman.154.1308496441.1164.python-list@python.org>

Show all headers | View raw


In article <mailman.154.1308496441.1164.python-list@python.org>,
 Chris Angelico <rosuav@gmail.com> wrote:

> On Mon, Jun 20, 2011 at 12:32 AM, TheSaint <nobody@nowhere.net.no> wrote:
> > Hello
> >
> > Trying to pop some key from a dict while is iterating over it will cause an
> > exception.
> > How I can remove items when the search result is true.
> >
> > Example:
> >
> > while len(dict):
> >   for key in dict.keys():
> >      if dict[key] is not my_result:
> >         dict.pop(key)
> >    else:
> >       condition_to_break
> > print('Dictionary is over')
> 
> One way is to iterate over an explicitly formed list of the keys.
> 
> for key in list(dict.keys()):
> 
> That creates an entirely new list with a snapshot copy of the keys. If
> you then remove elements from the dictionary, the list will still
> iterate correctly.

If the dict is large and you only want to remove a relatively small 
number of keys, you could instead build up a list of keys to be deleted 
and do them in a second pass:

# pseudo-code
pending_keys = []
for key in dict.keys():
  if dict[key] is not my_result:
    pending_keys.append(key)
for key in pending_keys:
  del dict[key]

Yet another variation which makes sense if you want to delete most of 
the keys would be to copy them to a new dictionary.  I'm not sure how 
Python handles memory management on dictionaries which shrink.  I'm 
guessing it doesn't do anything about resizing the hash table downwards, 
so you end up with a lot of wasted space.  This solves that problem:

# pseudo-code
new_dict = {}
for key in dict.keys():
  if dict[key] is my_result:
    new_dict[key] = dict[key]

although you could improve on that with iteritems() instead of keys().

Of course, of all these, Chris Angelico's original code is the most 
straight-forward, and that's would I would use unless you had some 
strong reason to believe performance was an issue.

Back to comp.lang.python | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

How to iterate on a changing dictionary TheSaint <nobody@nowhere.net.no> - 2011-06-19 22:32 +0800
  Re: How to iterate on a changing dictionary Chris Angelico <rosuav@gmail.com> - 2011-06-20 01:13 +1000
    Re: How to iterate on a changing dictionary Roy Smith <roy@panix.com> - 2011-06-19 11:53 -0400
      Re: How to iterate on a changing dictionary Terry Reedy <tjreedy@udel.edu> - 2011-06-19 12:51 -0400
  Re: How to iterate on a changing dictionary Terry Reedy <tjreedy@udel.edu> - 2011-06-19 12:02 -0400
  Re: How to iterate on a changing dictionary Lie Ryan <lie.1296@gmail.com> - 2011-06-20 03:00 +1000
    Re: How to iterate on a changing dictionary TheSaint <nobody@nowhere.net.no> - 2011-06-20 21:20 +0800
      Re: How to iterate on a changing dictionary Florencio Cano <florencio.cano@gmail.com> - 2011-06-20 16:30 +0200
      Re: How to iterate on a changing dictionary Terry Reedy <tjreedy@udel.edu> - 2011-06-20 13:37 -0400
        Re: How to iterate on a changing dictionary TheSaint <nobody@nowhere.net.no> - 2011-06-21 18:44 +0800

csiph-web