Ternary expression in dictionary comprehension

蓝咒 提交于 2019-12-30 07:00:14

问题


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.


回答1:


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).




回答2:


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


来源:https://stackoverflow.com/questions/21209402/ternary-expression-in-dictionary-comprehension

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!