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')
this is my mistake, but where to fix?
--
goto /dev/null
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.
I'm not sure what you're trying to do, but you may find it easier to
use the 'filter' function (which takes an iterable, so possibly use
dict.iteritems() for that).It'll keep some and not others, and then
you can make use of just the ones you get back.
Chris Angelico
> On Mon, Jun 20, 2011 at 12:32 AM, TheSaint <nob...@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.
The other is to make a set of to_be_deleted keys and delete them all
when done.
If you only want to delete one key, break the iteration and then delete.
> I'm not sure what you're trying to do, but you may find it easier to
> use the 'filter' function (which takes an iterable, so possibly use
> dict.iteritems() for that).It'll keep some and not others, and then
> you can make use of just the ones you get back.
--
Terry Jan Reedy
> 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.
'Python' does not handle memory management; each implementation does -).
I believe CPython will shrink lists and dicts that are too empty, but it
should be both more efficient and more dependable to make a new one as
with your code or
old_d = {i:i for i in range(100)}
d = {key:val for key,val in old_d.items() if not key%13}
d
>>>
{0: 0, 65: 65, 39: 39, 13: 13, 78: 78, 52: 52, 26: 26, 91: 91}
--
Terry Jan Reedy
Others has described how to do what you wanted to do, but let's address
the main problem here, why are you iterating a dictionary?
I found that most of the time that I thought I needed to iterate through
a dictionary, it's really because I'm thinking the wrong way, and a
little bit more thought lead me to a better way that doesn't involve
iterating on the dictionary.
While there are legitimate reasons for iterating a dictionary, I'd
consider the alternatives first.
Thank you all for the information, really apreciated.
> While there are legitimate reasons for iterating a dictionary, I'd
> consider the alternatives first.
Perhaps the correct answer is in what you said.
For certain reasons, searching in a dictionary is the fastest method,
secondly the positions of the data aren't relevant and easy to find.
My primer purpose is to know how much of work is done as soon the child
process reports completion of a part. The order of the given jobs are not
linear as it could do with a list.
To make an example: imaging Bingo.Shuffle the numbers, each number sorted
should be removed from the container, how would it implemented?
--
goto /dev/null
The structure seems a set -> unordered collection of unique elements.
You can select a random element from the set with
random.sample(container, num_of_elems)
And then remove the elem from the set with remove.
random.sample(someset) just turns the set into a sequence (tuple).
For bingo, where you will play multiple games,
start with an immutable collection balls = ('A1', 'A2', ...)
that you cannot accidentally modify and can repeatedly copy.
For each game, copy to a list game = list(balls).
Then random.shuffle(game), and game.pop() balls as needed.
Other situations will need other solutions.
--
Terry Jan Reedy
> Other situations will need other solutions.
>
Like a job's completion list.
Some number of workers get a job, and by time the caller sould know who and
what has finished. Then a dictionary would hold number of remaining jobs.
Similar a downloading list.
--
goto /dev/null
import re
myDict={'a':'alpha','b':'beta','c':'charley','d':'disney'}
myNewDict={}
for k,v in myDict.iteritems():
if re.search("a",v)!=None:
myNewDict[k]=v
print myDict
print myNewDict
Using regex is overkill. Try this instead:
if "a" in v: