The following code checks if x
and y
are distinct values (the variables x
, y
, z
can only have values a
, b
, or c
) and if so, sets z
to the third character:
if x == 'a' and y == 'b' or x == 'b' and y == 'a':
z = 'c'
elif x == 'b' and y == 'c' or x == 'c' and y == 'b':
z = 'a'
elif x == 'a' and y == 'c' or x == 'c' and y == 'a':
z = 'b'
Is is possible to do this in a more, concise, readable and efficient way?
Try this option, using dictionaries:
Of course, if the
x+y
key is not present in the map, it'll produce aKeyError
which you'll have to handle.If the dictionary is precomputed a single time and stored for future use, the access will be much faster, since no new data structures will have to be created for each evaluation, only a string concatenation and a dictionary lookup are needed:
Using list comprehension, assuming like others that one of the three cases in your code holds:
Or, like in the accepted answer, taking advantage of the tuple to unpack it,
See if this works
I think the solution by Sven Marnach and F.J is beautiful, but it's not faster in my little test. This is Raymond's optimized version using a pre-computed
set
:This is the original solution:
Note that this is the worst possible input for the
if
-statements since all six comparisons will have to be tried out. Testing with all values forx
andy
gives:The
set
-based variant shows the same performance for different inputs, but it is consistently between 2 and 8 times slower. The reason is that theif
-based variant runs much simpler code: equality tests compared to hashing.I think both types of solutions are valuable: it's important to know that creating "complicated" data structures like sets cost you something in performance — while they give you a lot in readability and development speed. The complex data types are also much better when the code change: it's easy to extend the set-based solution to four, five, ... variables whereas the if-statements quickly turn into a maintenance nightmare.
Sven's excellent code did just a little too much work and chould have used tuple unpacking instead of pop(). Also, it could have added a guard
if x != y
to check for x and y being distinct. Here is what the improved answer looks like:Here are the comparative timings with a timing suite to show the relative performance:
Here are the results of the timings:
These timings show that the original-version performance varies quite a bit depending on which if-statements are triggered by the various the input values.
or less hackish and using Conditional Assignment
but probably the dict solution is faster... you'd have to time it.