[Tutor] Iterate through dictionary values and remove item

GTXY20 gtxy20 at gmail.com
Thu May 15 18:58:03 CEST 2008


Hi Kent and Bob,

Bob sorry about the previous code snippet (was late) - I had previously been
trying to accomplish with the following:

for k,v in d.items():
    u=k[0]
    b=k[1]
    if 'a' in v:
        for k,v in d.items():
            if k[0] == u:
                for vals in v:
                    if vals == 'b':
                        v.remove('b')

this as mentioned was not performing very well at all.

Kent, I incorporated your suggestion:

toRemove=set(k[0] for k, v in d.iteritems() if 'b' in v)
for k,v in d.iteritems():
   if k[0] in toRemove:
       try:
           v.remove('b')
       except ValueError:
           pass

and the speed and result improved very dramatically. I suspect that I need
to get a better handle on the difference between items() and iteritems() and
what situations would call for them respectively.

Having said that, Kent I am not 100 percent sure of what you menat when you
mention a two-level dict. Can you give me a very brief example?

Thank you so much for your feedback.

G.

On Thu, May 15, 2008 at 7:57 AM, Kent Johnson <kent37 at tds.net> wrote:

>  On Thu, May 15, 2008 at 2:40 AM, GTXY20 <gtxy20 at gmail.com> wrote:
> > Hello all,
> >
> > I have dictionary like the following:
> >
> > d={(1,23A):[a,b,c,d],  (1,24A):[b,c,d], (2,23A):[a,b], (2,24A):[a,b,c,d]}
> >
> > I would like to iterate through the dictionary such that if it finds
> > the value 'a' in the values of the key that it would remove the value
> > 'b' from the values list. In addition if it finds 'a' in the values
> > list I would like it to take the first item from the key tuple k[0]
> > and and then look through the dictionary for that k[0] value and then
> > remove 'b' from its value list even if 'a' is not present in that
> > list. So at the end I would like my dictionary to end with:
> >
> > d={(1,23A):[a,c,d],  (1,24A):[c,d], (2,23A):[a], (2,24A):[a,c,d]}
> >
> > Initally I did the following:
> >
> > for k,v in d.items():
> > u=k[0]
> > b=k[1]
> > if 'a' in v:
> > for k,v in d.items():
> > if k[0] == u:
> > for values in v:
> > if values == 'b':
> > v.remove(values)
> >
> > However this will be a very big dictionary and it ended up running for
> > a very long time - in fact I had to kill the process.
>
> The main problem is the nested loops. Every time you find an 'a' you
> search the whole dict for items starting with matching keys.  There
> are some smaller problems as well - you could use d.iteritems()
> instead of d.items() to avoid creating intermediate lists, and there
> are better ways to remove 'b' from v.
>
> The first thing I would do is reduce this to two passes over the dict
> - the first pass can find the keys, the second to delete 'b' from the
> list. For example,
> toRemove=set(k[0] for k, v in d.iteritems() if 'b' in v)
> for k,v in d.iteritems():
>    if k[0] in toRemove:
>        try:
>            v.remove('b')
>        except ValueError:
>            pass
>
> If this is too slow, consider splitting up your keys - make a
> two-level dict so you can find all the keys starting with a particular
> value by a dict lookup instead of search.
>
> Kent
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/tutor/attachments/20080515/9157216b/attachment-0001.htm>


More information about the Tutor mailing list