Python:连接字符串列表if else oneliner



使用Pandas,我必须重写作为dict:实现的查询

query = {"height": 175}

键是查询的属性,值可以是标量或可迭代的。在第一部分中,我检查该值是否为not NaN and scalar。如果此条件成立,我将使用==符号编写查询表达式,但如果值为Iterable,我将需要使用in关键字编写表达式。这是我需要修复的实际代码,以便也能使用Iterables。

import numpy as np
from collections import Iterable

def query_dict_to_expr(query: dict) -> str:
expr = " and ".join(["{} == {}"
.format(k, v) for k, v in query.items()
if (not np.isnan(v)
and np.isscalar(v))
else "{} in @v".format(k) if isinstance(v, Iterable)
]
)
return expr

但我得到了与else语句对应的无效语法。

如果我理解正确,您不需要检查类型:

In [47]: query
Out[47]: {'height': 175, 'lst_col': [1, 2, 3]}
In [48]: ' and '.join(['{} == {}'.format(k,v) for k,v in query.items()])
Out[48]: 'height == 175 and lst_col == [1, 2, 3]'

演示:

In [53]: df = pd.DataFrame(np.random.randint(5, size=(5,3)), columns=list('abc'))
In [54]: df
Out[54]:
a  b  c
0  0  0  3
1  4  2  4
2  2  2  3
3  0  1  0
4  0  4  1
In [55]: query = {"a": 0, 'b':[0,4]}
In [56]: q = ' and '.join(['{} == {}'.format(k,v) for k,v in query.items()])
In [57]: q
Out[57]: 'a == 0 and b == [0, 4]'
In [58]: df.query(q)
Out[58]:
a  b  c
0  0  0  3
4  0  4  1

您在理解中放错了if/else。如果将if放在for之后,就像f(x) for x in iterable if g(x)一样,这将过滤可迭代的元素(并且不能与else组合(。相反,您希望保留所有元素,即使用f(x) for x in iterable,其中f(x)恰好是一个三元表达式,即形式为a(x) if c(x) else b(x)

相反,尝试如下(简化的非数字示例(:

>>> query = {"foo": 42, "bar": [1,2,3]}  
>>> " and ".join(["{} == {}".format(k, v)
if not isinstance(v, list)
else "{} in {}".format(k, v)
for k, v in query.items()])
'foo == 42 and bar in [1, 2, 3]'

最新更新