I'm trying to invert a dictionary. In the case of many keys having the same value, the new key (old value) should associate with a set of the new values (old keys). I solved the problem, but I'm trying to refactor using dictionary comprehension, and some helper methods.
def has_unique_value(k):
return d.values().count(d[k]) == 1
def keys_with_same_value_as_key(k):
return set([key for key in d.keys() if d[key] == d[k]])
print( {d[k]:k if has_unique_value(k) else d[k]:keys_with_same_value_as_key(k) for k in d.keys()} )
However, this raises a syntax error
print( {d[k]:k if has_unique_value(k) else d[k]:keys_with_same_value_as_key(k) for k in d} )
^
SyntaxError: invalid syntax
Hopefully the alignment in that code works right. It should point to the second :
, in the else
clause. Any idea what's up here? I've tried as many forms of parenthesizing as I can conceive.
All items in the dictionary are enclosed within a pair of curly braces {} . Each item in a dictionary is a mapping between a key and a value - called a key-value pair. A key-value pair is often called a dictionary item. You can access these values using the respective keys.
Practical Data Science using Python Similarly the ternary operator in python is used to return a value based on the result of a binary condition. It takes binary value(condition) as an input, so it looks similar to an “if-else” condition block. However, it also returns a value so behaving similar to a function.
The final if clause acts as a filter, which is different from having the conditional expression. Worth mentioning that you don't need to have an if-else condition for both the key and the value. For example, {(a if condition else b): value for key, value in dict. items()} will work.
Close!
The following code
d = {'a': 'x', 'b': 'y', 'c': 'x'}
def has_unique_value(k):
return d.values().count(d[k]) == 1
def keys_with_same_value_as_key(k):
return set([key for key in d.keys() if d[key] == d[k]])
print( {d[k]:k if has_unique_value(k) else keys_with_same_value_as_key(k) for k in d.keys()} )
Produces
{'y': 'b', 'x': set(['a', 'c'])}
The only difference is the second d[k]:
is removed.
In general, the ternary expression looks like
a = val_if_true if test else val_if_false
not something closer to what you had:
a = val_if_true if test else a = val_if_false
You specify where the value from the ternary expression should go once, at the beginning.
RE: Question in comments
This is still definitely a dictionary comprehension.
It's basically doing the following:
m = {}
for k in d.keys():
orig_key = k
orig_val = d[k]
if has_unique_value(k):
m[orig_val] = orig_key
else:
m[orig_val] = keys_with_same_value_as_key(orig_key)
print m
The only difference is that, in the dictionary comprehension, the m
dictionary is not kept in the namespace (and the variables orig_key
and orig_val
I used to clarify the code never exist).
The ternary expression can only be applied to one value and not to the equivalent of a dictionary assignment. Try this instead:
{d[k]: k if has_unique_value(k) else keys_with_same_value_as_key(k) for k in d.keys()}
Your first approach would be similar to the following (which does not work):
d[k] = k if k else d[k] = None # doesn't work
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With