python - 有没有更优雅的表达方式((x== a和y== b)或(x== b和y== a))?




boolean-logic (7)

作为对两个以上变量的概括,我们可以使用 itertools.permutations 。 那不是

(x == a and y == b and z == c) or (x == a and y == c and z == b) or ...

我们可以写

(x, y, z) in itertools.permutations([a, b, c])

当然还有两个变量版本:

(x, y) in itertools.permutations([a, b])

我正在尝试在Python中评估 ((x == a and y == b) or (x == b and y == a)) ,但这似乎有些冗长。 有没有更优雅的方式?


元组使其更具可读性:

(x, y) == (a, b) or (x, y) == (b, a)

这提供了一个线索:我们正在检查列表 x, y 是否等于列表 a, b 但忽略了排序。 那就是设置平等!

{x, y} == {a, b}

如果这些是数字,则可以使用 (x+y)==(a+b) and (x*y)==(a*b)

如果这些是可比较的项目,则可以使用 min(x,y)==min(a,b) and max(x,y)==max(a,b)

但是 ((x == a and y == b) or (x == b and y == a)) 清晰,安全并且更通用。


如果项目不可散列,但支持排序比较,则可以尝试:

sorted((x, y)) == sorted((a, b))

我认为最好的办法是将它们包装到元组中:

if (a, b) == (x, y) or (a, b) == (y, x)

或者,也许将其包装在集合中

if (a, b) in {(x, y), (y, x)}

正因为有几条评论提到了它,所以我做了一些计时,当查找失败时,元组和集合在这里的表现相同:

from timeit import timeit

x = 1
y = 2
a = 3
b = 4

>>> timeit(lambda: (a, b) in {(x, y), (y, x)}, number=int(5e7))
32.8357742

>>> timeit(lambda: (a, b) in ((x, y), (y, x)), number=int(5e7))
31.6169182

尽管查找成功时元组实际上更快:

x = 1
y = 2
a = 1
b = 2

>>> timeit(lambda: (a, b) in {(x, y), (y, x)}, number=int(5e7))
35.6219458

>>> timeit(lambda: (a, b) in ((x, y), (y, x)), number=int(5e7))
27.753138700000008

我选择使用集合是因为​​我正在执行成员资格查找,并且从概念上讲,集合比该元组更适合该用例。 如果您在特定用例中测量了两种结构之间的显着差异,请选择速度较快的一种。 我认为性能并不是这里的因素。


我认为,最优雅的方式是

(x, y) in ((a, b), (b, a))

如其他答案所示,这比使用集合(即 {a, b} == {y, x} 更好,因为我们不需要考虑变量是否可哈希。


您已经获得了最具可读性的解决方案 。 还有其他表达方式,也许用更少的字符,但是阅读起来却不那么直接。

根据值实际代表最好的选择的方式,是 将支票包装在一个具有语音名称的函数中 。 替代地或另外,您可以在专用的高级类对象中分别对对象x,y和a,b建模,然后可以在类相等性检查方法或专用的自定义函数中将其与比较逻辑进行比较。





boolean-logic