Is there a more elegant way to express ((x == a and y == b) or (x == b and y == a))?
I think the best you could get is to package them into tuples:
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 timeitx = 1y = 2a = 3b = 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 = 1y = 2a = 1b = 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. 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. That's just set equality!
{x, y} == {a, b}