Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #7963 > unrolled thread
| Started by | TheSaint <nobody@nowhere.net.no> |
|---|---|
| First post | 2011-06-19 22:32 +0800 |
| Last post | 2011-06-21 18:44 +0800 |
| Articles | 10 — 6 participants |
Back to article view | Back to comp.lang.python
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
| From | TheSaint <nobody@nowhere.net.no> |
|---|---|
| Date | 2011-06-19 22:32 +0800 |
| Subject | How to iterate on a changing dictionary |
| Message-ID | <itl1a5$rom$1@speranza.aioe.org> |
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')
this is my mistake, but where to fix?
--
goto /dev/null
[toc] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2011-06-20 01:13 +1000 |
| Message-ID | <mailman.154.1308496441.1164.python-list@python.org> |
| In reply to | #7963 |
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.
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
[toc] | [prev] | [next] | [standalone]
| From | Roy Smith <roy@panix.com> |
|---|---|
| Date | 2011-06-19 11:53 -0400 |
| Message-ID | <roy-3DDD62.11534419062011@news.panix.com> |
| In reply to | #7969 |
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.
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2011-06-19 12:51 -0400 |
| Message-ID | <mailman.161.1308502281.1164.python-list@python.org> |
| In reply to | #7974 |
On 6/19/2011 11:53 AM, Roy Smith wrote:
> 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
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2011-06-19 12:02 -0400 |
| Message-ID | <mailman.157.1308499346.1164.python-list@python.org> |
| In reply to | #7963 |
On 6/19/2011 11:13 AM, Chris Angelico 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.
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
[toc] | [prev] | [next] | [standalone]
| From | Lie Ryan <lie.1296@gmail.com> |
|---|---|
| Date | 2011-06-20 03:00 +1000 |
| Message-ID | <4dfe2b95$1@dnews.tpgi.com.au> |
| In reply to | #7963 |
On 06/20/11 00:32, TheSaint 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')
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.
[toc] | [prev] | [next] | [standalone]
| From | TheSaint <nobody@nowhere.net.no> |
|---|---|
| Date | 2011-06-20 21:20 +0800 |
| Message-ID | <itnhfp$ab0$1@speranza.aioe.org> |
| In reply to | #7986 |
Lie Ryan wrote: 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
[toc] | [prev] | [next] | [standalone]
| From | Florencio Cano <florencio.cano@gmail.com> |
|---|---|
| Date | 2011-06-20 16:30 +0200 |
| Message-ID | <mailman.182.1308580256.1164.python-list@python.org> |
| In reply to | #8013 |
> To make an example: imaging Bingo.Shuffle the numbers, each number sorted > should be removed from the container, how would it implemented? 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.
[toc] | [prev] | [next] | [standalone]
| From | Terry Reedy <tjreedy@udel.edu> |
|---|---|
| Date | 2011-06-20 13:37 -0400 |
| Message-ID | <mailman.184.1308591490.1164.python-list@python.org> |
| In reply to | #8013 |
On 6/20/2011 10:30 AM, Florencio Cano wrote:
>> To make an example: imaging Bingo.Shuffle the numbers, each number sorted
>> should be removed from the container, how would it implemented?
>
> 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
[toc] | [prev] | [next] | [standalone]
| From | TheSaint <nobody@nowhere.net.no> |
|---|---|
| Date | 2011-06-21 18:44 +0800 |
| Message-ID | <itpslk$cq4$1@speranza.aioe.org> |
| In reply to | #8020 |
Terry Reedy wrote: > 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
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web