1

I'm trying see how I can use a tuple in conditional statement like this:

(False_condition, True_Condition)[conditional expression]

Assign example values:

x, y = 4, 7

Conditional:

("x is greater than y", "x is less than y") [x < y]

Output:

'x is less than y'

Problem: What if x == y?

Assign value:

x,y = 5,5

Conditional:

("x is greater than y", "x is less than y", "x is equal to y") [x < y]

Output:

"x is greater than y"

Question: In this method, can you NOT have a third option?

SMJune
  • 407
  • 2
  • 12

4 Answers4

2

You can get to what you want with this:

print(( "x is less than y", "x is equal to y", "x is greater than y")[ [x<y,x==y,x>y].index(True)])
quamrana
  • 37,849
  • 12
  • 53
  • 71
  • Could you please explain how this works? What's happening? – SMJune Sep 20 '20 at 19:47
  • I put all three conditions in a list. Only one of them will be true and the index method reports the index of that one, which is then used to pick the text string from the tuple of the descriptions. – quamrana Sep 20 '20 at 20:26
  • this is actually the best solution. You can list any number of conditions this way, they all will be in the order, and it looks intuitive. – Kukuster Sep 21 '20 at 09:08
2

Here's what you want

("x is greater than y", "x is less than y", "x is equal to y")[(x < y) or (x==y)*2]

Looks weird, ha?

That's because in the square brackets after a tuple python expects a number. And the thing is, conditional false evaluates to 0 and conditional true evaluates to 1 with implicit type coercion.

So to make this work you would have to figure out a oneliner with conditionals, that will evaluate as follows:

  • 0 if x > y
  • 1 if x < y
  • 2 if x == y

We can utilize a so-called short-circuiting properties (see: https://stackoverflow.com/a/14892812).

  1. this guy x < y makes for the first 2 cases. We can separate it out with parenthesis: (x < y).
  2. with (x < y) or whatever, it will produce true (1) with the first statement if x < y and stop there, but if x < y happens to be false (0), then the or statement will proceed on evaluating the statement on the right, and return whatever, whatever it will be.
  3. so with (x < y) or (x==y)*2, if x < y then it will return true (1) right away, but if not: it will return (x==y)*2, which is either false (0) or true (1) multiplied by 2, so either 0 or 2.

Thus we have:

  • 0, if both x < y and x == y are false (i.e. x > y)
  • 1, if x < y returns true (1)
  • 2, if x < y is false, and x==y is true (1)

In fact, if we utilize short-circuiting properties of and statement, (x==y)*2 may be substituted to (x==y) and 2, yielding the same results, but running with a bit less CPU time. This approach may be used to refactor numbers of nested if statements that is intended to run a big number of times (usually > 1'000'000 times), and is called branchless programming.

P.S. You may want not to put everything in one line.

Kukuster
  • 135
  • 4
  • 10
0

You can use lambdas they are more efficient because in lambda only one expression will be evaluated unlike in tuple and Dictionary :

(lambda x,y:"x:{} is greater than y:{}".format(x,y), lambda x,y: "x:{} is less than y:{}".format(x,y) if x<y else "x:{} equal to y:{}".format(x,y))[x<=y](x,y)

enter image description here

dejanualex
  • 3,872
  • 6
  • 22
  • 37
0

What I usually use:

>>> for x, y in (1, 2), (2, 2), (2, 1):
        print('=<>'[(x < y) - (x > y)])

<
=
>

Although kukuster is right, or is faster. I might switch.

>>> for x, y in (1, 2), (2, 2), (2, 1):
        print('=<>'[(x < y) or -(x > y)])

<
=
>
Kelly Bundy
  • 23,480
  • 7
  • 29
  • 65