Reputation: 607
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
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
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