GTXY20 | 15 May 08:36
Picon

Iterate through dictionary values and remove item

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.
(Continue reading)

bob gailer | 15 May 13:01
Picon

Re: Iterate through dictionary values and remove item

GTXY20 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
(Continue reading)

Kent Johnson | 15 May 13:57
Gravatar

Re: Iterate through dictionary values and remove item

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
(Continue reading)

GTXY20 | 15 May 18:58
Picon

Re: Iterate through dictionary values and remove item

 
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

_______________________________________________
Tutor maillist  -  Tutor <at> python.org
http://mail.python.org/mailman/listinfo/tutor
Kent Johnson | 15 May 19:26
Gravatar

Re: Iterate through dictionary values and remove item

On Thu, May 15, 2008 at 12:58 PM, GTXY20 <gtxy20 <at> gmail.com> wrote:
> 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.

items() returns a list, iteritems() returns an iterator. If you don't
actually need an explicit list, iteritems() saves the cost of creating
it.

> 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?

Your dict d would look like this:
d={
    1: {23A:[a,b,c,d],  24A:[b,c,d]},
    2: {23A:[a,b], 24A:[a,b,c,d]}
  }

The top level would just use the first element of the current key; the
value would be another dict whose keys are the second element of the
current key. This makes it easy to find all the values whose first key
element is '1', for example. (You could also have the second element
be a list of tuples, that might be better if you just need to iterate
over it.)

Kent
_______________________________________________
Tutor maillist  -  Tutor <at> python.org
http://mail.python.org/mailman/listinfo/tutor

Ricardo Araoz | 16 May 15:01
Picon

Re: Iterate through dictionary values and remove item

Kent Johnson wrote:
> On Thu, May 15, 2008 at 12:58 PM, GTXY20 <gtxy20 <at> gmail.com> wrote:
>> 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.
> 
> items() returns a list, iteritems() returns an iterator. If you don't
> actually need an explicit list, iteritems() saves the cost of creating
> it.
> 
>> 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?
> 
> Your dict d would look like this:
> d={
>     1: {23A:[a,b,c,d],  24A:[b,c,d]},
>     2: {23A:[a,b], 24A:[a,b,c,d]}
>   }
> 

Lads...

 >>> d={
...     1: {23A:[a,b,c,d],  24A:[b,c,d]},
...     2: {23A:[a,b], 24A:[a,b,c,d]}
...   }
   File "<input>", line 2
     1: {23A:[a,b,c,d],  24A:[b,c,d]},
           ^
SyntaxError: invalid syntax
 >>>

Let's get a proper syntax for our data before attempting to process it.

_______________________________________________
Tutor maillist  -  Tutor <at> python.org
http://mail.python.org/mailman/listinfo/tutor


Gmane