Syzorr
Syzorr

Reputation: 607

Using List Comprehension with Dictionaries in Python

I'm trying to get my head around list comprehensions and I can understand the basics of how they work but I get the feeling I should be able to do something with my code here that I just can't seem to get working.

Given a dictionary:

{2: {11},  9: {11, 8, 10}, 10: {11, 3}, 11: {7, 5},  8: {7, 3}}

There are a couple of snippets that I feel I should be able to reduce to fewer lines if I knew better:

for k, v in d.items():
    dag[k] = v
    for val in v:
        if val not in d.keys():
            dag[val] = None

and:

t = []
for k, v in d.items():
    if not v:
        t.append(k)
        d.pop(k)

My attempts have been variations on:

for [k, v in d.items() if not v]:

But that keeps telling me it needs an else statement and none of what I have read has helped answer how/if this is possible.

Upvotes: 2

Views: 19530

Answers (2)

Martijn Pieters
Martijn Pieters

Reputation: 1121924

In your first snippet, you are essentially defaulting all nodes to None in the dag. You could invert those steps and avoid testing for keys already being present altogether:

dag = dict.fromkeys(node for v in d.values() for node in v)
dag.update(d)

This creates a dictionary with all None values for the given keys (sourced from a generator expression), then updated to insert all known edges.

In your code you used if val not in d.keys(); this is functionally equivalent to if val not in d, but without the redundant call to d.keys(), which creates a new object (in Python 2, a list with all keys, making the search extra inefficient, in Python 3 a dictionary view is created). Always use the shorter form there.

Do be aware that the set objects you use as values in d are now shared with dag; any changes you make to these sets will be reflected across both dictionaries.

Creating a sequence of nodes without values would then be:

nodes_without_exits = [node for node, edges in d.items() if not node]

List comprehensions still need the producer expression, the part that produces the value to be inserted into the list; here that's node, the list is built out of the keys of the dictionary.

Upvotes: 1

Padraic Cunningham
Padraic Cunningham

Reputation: 180411

If you want to keep the keys that have falsey values the syntax is:

[ k for k, v in d.items() if not v]

That is equivalent to your last loop bar the d.pop(k) which I am not sure if you want. The first k is what we append to the list, for k, v is each key and value in d.items and if not v means we only keep the k's that have falsey values.

If you actually want a dict without those keys and value you can use a dict comprehension where the logic is exactly the same except we are creating key/value pairings instead of just keeping just the keys in the list comprehension:

{ k:v for k, v in d.items() if not v}

As for your first code, I am not sure what you want it to do exactly but you should not be calling .keys, in python2 that creates a list and makes lookups O(n) as opposed to 0(1) and in python 3 it is an unnecessary function call.

Upvotes: 4

Related Questions