469,923 Members | 1,745 Online

# Removing dictionary-keys not in a set?

Hi,

I'd like to remove keys from a dictionary, which are not found in a
specific set. So it's kind of an intersection-operation.

I can create a new dictionary, or a loop over all keys and test them
for set-membership, but I was wondering if there was a smart way to
express this in 1 or 2 concise statements that I'm not aware of.

So are there smarter ways to get the intersection of dictionary and set
into a dictionary than the following pseudo-code:

# Variation 1
d2 = {}
for key in s: d2[key] = d1[key]

# Variation 2
for key in d.iterkeys(): if key not in s: del d[key]
And if there's no smarter way, then which of these two options would
give best performance?

Cheers,

--Tim

Jul 19 '05 #1
9 3132
Hi,

I am not sure if this way is a good one, but it certainly is consise.
Also sometimes, it's better to go for a simple approach than the consise
one (for readability). With the abive disclaimer, I present my solution:

d1 = {1 : 2, 3 : 4, 5 : 6, 7 : 8, 9 : 10 }
s1 = [ 1, 5, 7 ]

# assuming you are using python 2.3.5
import sets
d2 = dict( [ ( x, d1[ x ] ) for x in sets.Set( d1.keys() ).
intersection( sets.Set( s1 ) ) ] )
thanks,
Satchit
Tim N. van der Leeuw wrote:
Hi,

I'd like to remove keys from a dictionary, which are not found in a
specific set. So it's kind of an intersection-operation.

I can create a new dictionary, or a loop over all keys and test them
for set-membership, but I was wondering if there was a smart way to
express this in 1 or 2 concise statements that I'm not aware of.

So are there smarter ways to get the intersection of dictionary and set
into a dictionary than the following pseudo-code:

# Variation 1
d2 = {}
for key in s: d2[key] = d1[key]

# Variation 2
for key in d.iterkeys(): if key not in s: del d[key]
And if there's no smarter way, then which of these two options would
give best performance?

Cheers,

--Tim

Jul 19 '05 #2
Tim N. van der Leeuw wrote:
Hi,

I'd like to remove keys from a dictionary, which are not found in a
specific set. So it's kind of an intersection-operation.

I can create a new dictionary, or a loop over all keys and test them
for set-membership, but I was wondering if there was a smart way to
express this in 1 or 2 concise statements that I'm not aware of.

So are there smarter ways to get the intersection of dictionary and set
into a dictionary than the following pseudo-code:

# Variation 1
d2 = {}
for key in s: d2[key] = d1[key]

# Variation 2
for key in d.iterkeys(): if key not in s: del d[key]

You could try a generator expression:

py> d = {1: 2, 3: 4, 5: 6, 7: 8, 9: 10}
py> s = set([1, 5, 7])
py> dict((k, v) for k, v in d.iteritems() if k in s)
{1: 2, 5: 6, 7: 8}

Note that your variation 2 won't work:

py> for key in d.iterkeys():
.... if key not in s:
.... del d[key]
....
Traceback (most recent call last):
File "<interactive input>", line 1, in ?
RuntimeError: dictionary changed size during iteration

You can make it work using keys() instead of iterkeys():

py> for key in d.keys():
.... if key not in s:
.... del d[key]
....
py> d
{1: 2, 5: 6, 7: 8}

But I think I'd probably lean towards the generator expression...

STeVe
Jul 19 '05 #3
Tim N. van der Leeuw <ti*************@nl.unisys.com> wrote:

I'd like to remove keys from a dictionary, which are not found in a
specific set. So it's kind of an intersection-operation.

Why not just use the builtin set operations?
--
Aahz (aa**@pythoncraft.com) <*> http://www.pythoncraft.com/

"The joy of coding Python should be in seeing short, concise, readable
classes that express a lot of action in a small amount of clear code --
not in reams of trivial code that bores the reader to death." --GvR
Jul 19 '05 #4
Tim N. van der Leeuw wrote:
I'd like to remove keys from a dictionary, which are not found
in a specific set. So it's kind of an intersection-operation.

#v+

klaus@home:~ \$ python
Python 2.4.1 (#2, Mar 30 2005, 21:51:10)
[GCC 3.3.5 (Debian 1:3.3.5-8ubuntu2)] on linux2
d1 = {1:'a', 2:'b', 3:'c', 4:'d', 5:'e'}
s1 = set(d1)
s1 set([1, 2, 3, 4, 5]) s2 = set([1, 3, 5])
s1-s2 set([2, 4]) for k in s1-s2: .... del d1[k]
.... d1 {1: 'a', 3: 'c', 5: 'e'} ^D

klaus@home:~ \$

#v-

--
Klaus Alexander Seistrup
Magnetic Ink, Copenhagen, Denmark
http://magnetic-ink.dk/
Jul 19 '05 #5
Hi Aahz,

The problem with using the builtin set operations is, that the
dictionary keys don't represent a set, so you can't directly create a
new dictionary using set methods.

So I'm looking for what's a concise way to update a dictionary, or
create a new dictionary, using basically an intersection method.

(I'm using Python 2.4.1 so I do have convenient builtin set operations
available)

In my taste, using generator expressions with conditions actually
doesn't look very readable; it hides the set-membership test under the
syntactic clutter.
(I don't mind generator expressions in principle, but I do feel that
here they clutter up the intent of the code)

cheers,

--Tim

Jul 19 '05 #6
Hi Klaus,

I think I like the looks of your version the best, so far. Readable and
clear, to me.

cheers and thanks,

--Tim

Jul 19 '05 #7
Tim N. van der Leeuw wrote:
In my taste, using generator expressions with conditions actually
doesn't look very readable; it hides the set-membership test under the
syntactic clutter.

You might try different indentation. I find that I write a lot of my
list comprehensions and generator expressions like:

dict((k, v)
for k, v in d.iteritems()
if k in s)

It looks much more like the for-loop in my mind, and I can easily spot
each of the for- and if-expressions in the genexp.

STeVe
Jul 19 '05 #8
"Tim N. van der Leeuw" <ti*************@nl.unisys.com> wrote in message news:<11**********************@l41g2000cwc.googleg roups.com>...
Hi,

I'd like to remove keys from a dictionary, which are not found in a
specific set.

Here's my magic English-to-Python translator:

"I'd like to ... keys which ..." -> "for key in"
"keys from a dictionary" -> "set(dictionary)"
"... remove keys ..." -> "del dictionary[key]"

Putting it all together:
for key in set(dictionary)-specificset:

.... del dictionary[key]

Oren
Jul 19 '05 #9
[Klaus Alexander Seistrup]
d1 = {1:'a', 2:'b', 3:'c', 4:'d', 5:'e'}
s1 = set(d1)
s1 set([1, 2, 3, 4, 5]) s2 = set([1, 3, 5])
s1-s2 set([2, 4]) for k in s1-s2:

... del d1[k]
...

FWIW, if s2 is not already a set object, it need not be transformed before using

for k in set(d1).difference([1,3,5]):
del d1[k]

If you prefer to work with dictionaries instead of sets, then adapt the existing
code for symmetric_difference_update() in sets.py.

Raymond Hettinger
Jul 19 '05 #10

### This discussion thread is closed

Replies have been disabled for this discussion.