Respuestas:
Ya lo tienes: A if test else B
es una expresión válida de Python. El único problema con su comprensión dict como se muestra es que el lugar para una expresión en una comprensión dict debe tener dos expresiones, separadas por dos puntos:
{ (some_key if condition else default_key):(something_if_true if condition
else something_if_false) for key, value in dict_.items() }
La if
cláusula final actúa como un filtro, que es diferente de tener la expresión condicional.
{(a if condition else b): value for key, value in dict.items()}
funcionará.
La respuesta de @ Marcin lo cubre todo, pero en caso de que alguien quiera ver un ejemplo real, agrego dos a continuación:
Digamos que tienes el siguiente diccionario de conjuntos
d = {'key1': {'a', 'b', 'c'}, 'key2': {'foo', 'bar'}, 'key3': {'so', 'sad'}}
y desea crear un nuevo diccionario cuyas claves indiquen si la cadena 'a'
está contenida en los valores o no, puede usar
dout = {"a_in_values_of_{}".format(k) if 'a' in v else "a_not_in_values_of_{}".format(k): v for k, v in d.items()}
cuyos rendimientos
{'a_in_values_of_key1': {'a', 'b', 'c'},
'a_not_in_values_of_key2': {'bar', 'foo'},
'a_not_in_values_of_key3': {'sad', 'so'}}
Ahora supongamos que tiene dos diccionarios como este
d1 = {'bad_key1': {'a', 'b', 'c'}, 'bad_key2': {'foo', 'bar'}, 'bad_key3': {'so', 'sad'}}
d2 = {'good_key1': {'foo', 'bar', 'xyz'}, 'good_key2': {'a', 'b', 'c'}}
y desea reemplazar las claves d1
por las claves de d2
si sus valores respectivos son idénticos, podría hacer
# here we assume that the values in d2 are unique
# Python 2
dout2 = {d2.keys()[d2.values().index(v1)] if v1 in d2.values() else k1: v1 for k1, v1 in d1.items()}
# Python 3
dout2 = {list(d2.keys())[list(d2.values()).index(v1)] if v1 in d2.values() else k1: v1 for k1, v1 in d1.items()}
lo que da
{'bad_key2': {'bar', 'foo'},
'bad_key3': {'sad', 'so'},
'good_key2': {'a', 'b', 'c'}}
d1
, d2
obtengoAttributeError: 'dict_values' object has no attribute 'index'
En caso de que tenga diferentes condiciones para evaluar las claves y los valores, la respuesta de @ Marcin es el camino a seguir.
Si tiene la misma condición para las claves y los valores, es mejor construir tuplas (clave, valor) en una expresión de generador que alimenta dict()
:
dict((modify_k(k), modify_v(v)) if condition else (k, v) for k, v in dct.items())
Es más fácil de leer y la condición solo se evalúa una vez por clave, valor.
Ejemplo con tomar prestado el diccionario de conjuntos de @ Cleb:
d = {'key1': {'a', 'b', 'c'}, 'key2': {'foo', 'bar'}, 'key3': {'so', 'sad'}}
Supongamos que desea sufijo solamente keys
con a
en su value
y desea que la value
reemplazó con la longitud del conjunto en un caso así. De lo contrario, el par clave-valor debería permanecer sin cambios.
dict((f"{k}_a", len(v)) if "a" in v else (k, v) for k, v in d.items())
# {'key1_a': 3, 'key2': {'bar', 'foo'}, 'key3': {'sad', 'so'}}
Otro ejemplo en el uso de if / else en la comprensión del diccionario
Estoy trabajando en la aplicación de escritorio de entrada de datos para mi propio trabajo de oficina, y es común que dicha aplicación de entrada de datos obtenga todas las entradas del widget de entrada y las descargue en un diccionario para su posterior procesamiento como validación o edición, que debemos devolver datos seleccionados desde el archivo de regreso a los widgets de entrada, etc.
La primera ronda con codificación tradicional (8 líneas):
entries = {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}
a_dic, b_dic = {}, {}
for field, value in entries.items():
if field == 'ther':
for k,v in value.items():
b_dic[k] = v
a_dic[field] = b_dic
else:
a_dic[field] = value
print(a_dic)
“ {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}”
En la segunda ronda, intenté usar la comprensión del diccionario, pero el bucle sigue ahí (6 líneas):
entries = {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}
for field, value in entries.items():
if field == 'ther':
b_dic = {k:v for k,v in value.items()}
a_dic[field] = b_dic
else:
a_dic[field] = value
print(a_dic)
“ {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}”
Finalmente, con una declaración de comprensión de diccionario de una línea (1 línea):
entries = {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}
a_dic = {field:{k:v for k,v in value.items()} if field == 'ther'
else value for field, value in entries.items()}
print(a_dic)
“ {'name': 'Material Name', 'maxt': 'Max Working Temperature', 'ther': {100: 1.1, 200: 1.2}}”
Yo uso python 3.8.3
dict
está hecho dekey:value
elementos, no estás construyendo undict
aquí sino unset
(ver conjunto de literales ).