Iterating over dict and removing some elements

U

Ulrich Eckhardt

Hi!

I wrote a simple loop like this:

d = {}
...
for k in d:
if some_condition(d[k]):
d.pop(k)

If I run this, Python complains that the dictionary size changed during
iteration. I understand that the iterator relies on the internal structure
not changing, but how would I structure this loop otherwise?

My first approach was to simply postpone removing the elements, but I was
wondering if there was a more elegant solution.

Thanks!

Uli
 
M

Michele Simionato

Or you copy the whole dictionary or you just copy the keys:

for k in d.keys():
...

or

for k in list(d):
...
 
J

Jerry Hill

My first approach was to simply postpone removing the elements, but I was
wondering if there was a more elegant solution.

Iterate over something other than the actual dictionary, like this:

d = {1: 'one', 2: 'two', 3: 'three'}

for k in d.keys():
if d[k] == 'two':
d.pop(k)
 
T

Terry Reedy

My first approach was to simply postpone removing the elements, but I was
wondering if there was a more elegant solution.

Iterate over something other than the actual dictionary, like this:

d = {1: 'one', 2: 'two', 3: 'three'}

for k in d.keys():
if d[k] == 'two':
d.pop(k)

This, as written, does not work in 3.1, where d.keys is a view of the
dict. Nor does

for k in filter(lambda k: d[k] == 'two', d):
d.pop(k)

But these do

for k in list(filter(lambda k: d[k] == 'two', d)):
d.pop(k)

for k in [k for k in d if d[k] == 'two']:
d.pop(k)

Rather than make an external list of *all* keys, one only needs to make
a list of keys to be removed, which often will be much smaller.

Terry Jan Reedy
 
R

Rebelo

Hi!

I wrote a simple loop like this:

d = {}
...
for k in d:
if some_condition(d[k]):
d.pop(k)

If I run this, Python complains that the dictionary size changed during
iteration. I understand that the iterator relies on the internal structure
not changing, but how would I structure this loop otherwise?

My first approach was to simply postpone removing the elements, but I was
wondering if there was a more elegant solution.

Thanks!

Uli


i am wondering why not like this:
.... if k==1:
.... del d[k]
....
 
B

Bryan

Rebelo said:
i am wondering why not like this:

 >>> d = {1: 'one', 2: 'two', 3: 'three'}
 >>> for k,v in d.items():
...     if k==1:
...          del d[k]
...
 >>> d
{2: 'two', 3: 'three'}
 >>>

Mostly because there's no reason to get 'v' if you're not going to use
it. That may be just because you simplified the example, and if you
are working in Python 2.x and the real test for whether to delete
involves the value and not just the key, that's a reasonable solution.

On subtler issues, it constucts an unnecessarily long temporary list
in current Python 2.X, and fails in Python 3.x, as Terry Ready
explained.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top