0

Implicitly defined functions in python are confusing me.

I have a dict

cluster={"coords":set([i,j]), "var2":x[i]<0.05 or x[j]<0.05, "var3":x[i]>0.95 or x[j]>0.95, "var4":v4}

[previously dict={"var1":set([i,j]), "var2":x[i]<0.05 or x[j]<0.05, "var3":x[i]>0.95 or x[j]>0.95, "var4":v4}] changed variables to make it clear

So the next line of code reduces certain redundant [i,j] coords to an empty set so that coords = {}. I am having trouble then removing the "cluster" entries with coords = {}, so that only "cluster" elements with elements in cluster exist (basically filter out the empty ones by the value of coords).

I'm using python 2.7 so the dict list doesn't work for me.

3 Answers3

2

This should work:

dd = dict((k, v) for k, v in d.items() if v != set())

This is a simple dict comprehension and filters out empty (falsy) values of v.

Note:

  • Don't name variables dict shadowing the builtin dict type.
  • This creates a new dict rather than modifying the existing dict instance.
James Mills
  • 18,669
  • 3
  • 49
  • 62
2

If I understand your question correctly, you want to delete items in a dictionary where the value is an empty set.

for k,v in dict.items():
    if v == set():
        del dict[k]

That should empty out all key value pairs with value of an empty set.

As said in the comments, dict.items() is only safe in Python 2.x. In 3.x, you can use list(dict.items()).

The reason being, it isn't safe to modify a dictionary while iterating through it. items will return a list of tuples in Python 2.x, which will remain static while you iterate through it. items in Python 3.x will keep checking dict through each iteration, thus iterating through an object that is getting modified. This is unsafe and unpredictable.

johannestaas
  • 1,175
  • 1
  • 9
  • 15
  • 1
    It isn't safe to modify a dictionary while iterating over it with `.items()` (depending on python version). Use `list(dict.items())` in python3. – Tim Dec 14 '13 at 02:08
  • 1
    In 2, yes. In 3 it is an iterator. It isn't clear what version the questioner is using, so it's worth mentioning that it's unsafe in 3. – Tim Dec 14 '13 at 02:14
  • Is the note I added accurate? I didn't know Python 3 would have a different generator implementation for `items`. – johannestaas Dec 14 '13 at 06:17
1

To determine if some variable x is an empty set, you could use this:

if isinstance(x, set) and len(x) == 0:
    ...

I suggest using list(dict.items()) (assuming Python 3). dict.items()returns a view over the keys and values as tuples; this view will become modified when items are deleted from the dict even as you iterate through its items. This can cause problems, so wrapping list around it will create a copy of this returned view and prevent these problems. (A "view" is actually a generator, which you can read about here)

for (key, value) in theDict.items():
    if isinstance(value, set) and len(value) == 0: # note len(value) only computed if value is a set, so no worries about calling len on something that has no __len__ defined.
        del theDict[key]

A note about conventions: the name dict is already used for the built-in Python function of that name, so consider using another variable name.

Community
  • 1
  • 1
SimonT
  • 2,219
  • 1
  • 18
  • 32