简体   繁体   English

有没有更优雅的方式来表达 ((x == a and y == b) 或 (x == b and y == a))?

[英]Is there a more elegant way to express ((x == a and y == b) or (x == b and y == a))?

I'm trying to evaluate ((x == a and y == b) or (x == b and y == a)) in Python, but it seems a bit verbose.我正在尝试评估 Python 中((x == a and y == b) or (x == b and y == a)) ,但这似乎有点冗长。 Is there a more elegant way?有没有更优雅的方式?

If the elements are hashable, you could use sets:如果元素是可散列的,则可以使用集合:

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

I think the best you could get is to package them into tuples:我认为你能得到的最好的是将 package 变成元组:

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

Or, maybe wrap that in a set lookup或者,也许将其包装在一个集合查找中

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

Just since it was mentioned by a couple comments, I did some timings, and tuples and sets appear to perform identically here when the lookup fails:就因为有几条评论提到了它,我做了一些计时,当查找失败时,元组和集合似乎在这里执行相同的操作:

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

Although tuples are actually faster when the lookup succeeds:虽然查找成功时元组实际上更快:

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

I chose to use a set because I'm doing a membership lookup, and conceptually a set is a better fit for that use-case than a tuple.我选择使用集合是因为我正在进行成员资格查找,并且从概念上讲,集合比元组更适合该用例。 If you measured a significant different between the two structures in a particular use case, go with the faster one.如果您在特定用例中测量了两种结构之间的显着差异,则 go 与更快的一个。 I don't think performance is a factor here though.我不认为性能是这里的一个因素。

Tuples make it slightly more readable:元组使其更具可读性:

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

This gives a clue: we're checking whether the sequence x, y is equal to the sequence a, b but ignoring ordering.这给出了一个线索:我们正在检查序列x, y是否等于序列a, b但忽略排序。 That's just set equality!那只是设定平等!

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

The most elegant way, in my opinion, would be在我看来,最优雅的方式是

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

This is a better way than using sets, ie {a, b} == {y, x} , as indicated in other answers because we don't need to think if the variables are hashable.这是比使用集合更好的方法,即{a, b} == {y, x} ,如其他答案所示,因为我们不需要考虑变量是否是可散列的。

If the items aren't hashable, but support ordering comparisons, you could try:如果项目不可散列,但支持排序比较,您可以尝试:

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

If these are numbers, you can use (x+y)==(a+b) and (x*y)==(a*b) .如果这些是数字,您可以使用(x+y)==(a+b) and (x*y)==(a*b)

If these are comparable items, you can use min(x,y)==min(a,b) and max(x,y)==max(a,b) .如果这些是可比较的项目,您可以使用min(x,y)==min(a,b) and max(x,y)==max(a,b)

But ((x == a and y == b) or (x == b and y == a)) is clear, safe, and more general.但是((x == a and y == b) or (x == b and y == a))是清晰、安全和更通用的。

As a generalization to more than two variables we can use itertools.permutations .作为对两个以上变量的概括,我们可以使用itertools.permutations That is instead of那是代替

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

we can write我们可以写

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

And of course the two variable version:当然还有两个可变版本:

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

You can use tuples to represent your data and then check for set inclusion, like:您可以使用元组来表示您的数据,然后检查集合包含,例如:

def test_fun(x, y):
    test_set = {(a, b), (b, a)}

    return (x, y) in test_set

You already got the most readable solution .您已经获得了最易读的解决方案 There are other ways to express this, perhaps with less characters, but they are less straight-forward to read.还有其他方式来表达这一点,也许用更少的字符,但它们不那么直截了当。

Depending on what the values actually represent your best bet is to wrap the check in a function with a speaking name .根据实际代表的值,您最好的选择是将支票包装在 function 中,并带有口语名称 Alternatively or in addition, you can model the objects x,y and a,b each in dedicated higher class objects that you then can compare with the logic of the comparison in a class equality check method or a dedicated custom function. Alternatively or in addition, you can model the objects x,y and a,b each in dedicated higher class objects that you then can compare with the logic of the comparison in a class equality check method or a dedicated custom function.

It seems the OP was only concerned with the case of two variables, but since StackOverflow is also for those who search for the same question later, I'll try to tackle the generic case here in some detail;似乎 OP 只关心两个变量的情况,但由于 StackOverflow 也适用于稍后搜索相同问题的人,所以我将尝试在这里更详细地解决一般情况; One previous answer already contains a generic answer using itertools.permutations() , but that method leads to O(N*N!) comparisons, since there are N!以前的一个答案已经包含使用itertools.permutations()的通用答案,但是该方法导致O(N*N!)比较,因为有N! permutations with N items each.每个有N个项目的排列。 (This was the main motivation for this answer) (这是这个答案的主要动机)

First, let's summarize how some of the methods in previous answers apply to the generic case, as motivation for the method presented here.首先,让我们总结一下先前答案中的一些方法如何应用于一般情况,作为此处介绍的方法的动机。 I'll be using A to refer to (x, y) and B to refer to (a, b) , which can be tuples of arbitrary (but equal) length.我将使用A来引用(x, y)B来引用(a, b) ,它可以是任意(但相等)长度的元组。

set(A) == set(B) is fast, but only works if the values are hashable and you can guarantee that one of the tuples doesn't contain any duplicate values. set(A) == set(B)速度很快,但仅在值是可散列的并且您可以保证其中一个元组不包含任何重复值时才有效。 (Eg. {1, 1, 2} == {1, 2, 2} , as pointed out by @user2357112 under @Daniel Mesejo's answer) (例如{1, 1, 2} == {1, 2, 2} ,正如@user2357112在@Daniel Mesejo 的回答下指出的那样)

The previous method can be extended to work with duplicate values by using dictionaries with counts, instead of sets: (This still has the limitation that all values need to be hashable, so eg mutable values like list won't work)以前的方法可以通过使用带有计数的字典而不是集合来扩展以处理重复值:(这仍然具有所有值都需要是可散列的限制,因此例如像list这样的可变值将不起作用)

def counts(items):
    d = {}
    for item in items:
        d[item] = d.get(item, 0) + 1
    return d

counts(A) == counts(B)

sorted(A) == sorted(B) doesn't require hashable values, but is slightly slower, and requires orderable values instead. sorted(A) == sorted(B)不需要可散列的值,但速度稍慢,而是需要可排序的值。 (So eg complex won't work) (所以例如complex不起作用)

A in itertools.permutations(B) doesn't require hashable or orderable values, but like already mentioned, it has O(N*N!) complexity, so even with just 11 items, it can take over a second to finish. A in itertools.permutations(B)不需要可散列或可排序的值,但如前所述,它具有O(N*N!)复杂性,因此即使只有 11 个项目,也可能需要一秒钟才能完成。

So, is there a way to be as general, but do it considerably faster?那么,有没有办法做到通用,但速度要快得多? Why yes, by "manually" checking that there's the same amount of each item: (The complexity of this one is O(N^2) , so this isn't good for large inputs either; On my machine, 10k items can take over a second - but with smaller inputs, like 10 items, this is just as fast as the others)为什么是的,通过“手动”检查每个项目的数量是否相同:(这个项目的复杂性是O(N^2) ,所以这也不适用于大输入;在我的机器上,10k 个项目可以占用超过一秒钟 - 但输入较小,如 10 个项目,这与其他项目一样快)

def unordered_eq(A, B):
    for a in A:
        if A.count(a) != B.count(a):
            return False
    return True

To get the best performance, one might want to try the dict -based method first, fall back to the sorted -based method if that fails due to unhashable values, and finally fall back to the count -based method if that too fails due to unorderable values.为了获得最佳性能,人们可能想先尝试基于dict的方法,如果由于不可散列的值而失败,则回退到基于sorted的方法,如果由于不可散列的值而失败,最后回退到基于count的方法不可排序的值。

If we are not looking for Python syntax specific answer如果我们不是在寻找 Python 语法特定答案

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 查找从a到b的数字不能被x到y整除 - Finding numbers from a to b not divisible by x to y 将格式为M = [((a,x),(b,y)]]的列表分成M1 = [a,b]和M2 = [x,y] - Separate lists of format M=[(a,x), (b,y)] into M1=[a,b] and M2=[x,y] PYTHON:解决 y=a+b*x 其中 x 是预定义列表 - PYTHON: solving y=a+b*x where x is a predefined list Sympy 反函数:y = ax+b 变为 x = (yb)/a - Sympy Inverse a function: y = ax+b into x = (y-b)/a 什么是pythonic方式在R中执行dt [,y:= myfun(x),by = list(a,b,c)]? - What is pythonic way to do dt[,y:=myfun(x),by=list(a,b,c)] in R? 检查表 B 中的 X、Y 列对是否在表 A 中任何 X、Y 列对的增量距离内 - Check if X,Y column pair in table B is within delta distance of any X, Y column pair in table A 在复平面和corr中找到A(x)和B(y)的交点。 x和y - Find intersection of A(x) and B(y) in complex plane plus corr. x and y 如何在无序的情况下简化“for for in in in in in in in in b in z in c ...”? - How can I simplify “for x in a for y in b for z in c …” with the unordered? 在Python中以y =a*x+b的形式学习线性模型 - Learning a Linear Model in Python in the form of y =a*x+b 满足以下约束的纸浆程序 min(a,b) > min(x,y) - pulp program for the the following constraint min(a,b) > min(x,y)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM