0

I'm currently working on a project where a lot of different accounting is done and I came to see this pattern very often:

if A > X:
    B += 1
else:
    C += 1

I know ternary operator but if I understand it correctly the shortest way how to utilize it would be:

B += 1 if A > X else False
C += 1 if A <= X else False

since ternary operator is connected to the variable used in its head. So using ternary operator is obviously worse than the previous if/else both from computational and readability standpoint.

The other idea was to create a simple function like this:

conditional_bumper(positive_case_var, negative_case_var, condition_var, compare_to=0)

then the usage looks like:

conditional_bumper(B, C, A, X)  # X being optional

so I can one line it every time I see it but at the same time this seems to me like a very 'hacky' solution. Is there a better way I don't see?

12
  • 4
    Whats wrong with the original pattern? Commented Oct 8, 2020 at 12:56
  • 1
    Imo readability wins over "one-liners". Commented Oct 8, 2020 at 12:57
  • 1
    Seems like you are counting the number of times that A > X. If this is a case, there is probably a way you can utilize collections.Counter Commented Oct 8, 2020 at 12:59
  • 1
    If you don't care about readability at all, you could write this even shorter as B += A > X; C += A <= X - your second code block is relying on the fact that False has a numeric value of 0, might as well rely on True having a value of 1 as well. Commented Oct 8, 2020 at 13:00
  • 1
    @VPfB Using 0 if A>X else 1 is a bit counter-intuitive (especially if treating 0 as the "truthy" case) since booleans can be used as keys directly. See my answer Commented Oct 8, 2020 at 13:29

6 Answers 6

3

Try this Pal! Hope this gives you a north of this matter. Cheers!

    # declare and initialize variables
    B, C = 0, 0
    A, X = 1, 2
    
    # ternary operator to work with this conditional
    B,C = (B + 1, C) if A > X else(B,C + 1)
    
    #display results
    print(B,C)
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, this seems as the best option so far. :)
Glad to be of help, pal!
1

I think that the more readable you'r code is, the better is. " One line " code works but it's not viable

1 Comment

I agree with you, I don't want to sacrifice readability I simply wonder if I can get better solution overall because in a way having that original pattern in the code makes it long and less readable.
1

If you are really after a one-liner and don't care about readability (which you shouldn't), you can use this old trick (at the cost of building a list and having a somewhat cryptic code)

A = 2
B = 0
C = 0
X = 3

CB = [C, B]
print(CB)
CB[A > X] += 1
print(CB)

# [0, 0]
# [1, 0]

Note that C and B themselves are not modified, the change is only visible through the CB list.

This works because A > X evaluates to True or False, which can be used for indexing since bool subclasses int.

A better approach using a dict

Another less cryptic option is to use a dict instead. I think this is actually a better option. You can even use meaning full names :)

A = 2
X = 3

times_a_greater_than_x = {True: 0, False: 0}
times_a_greater_than_x [A > X] += 1
print(times_a_greater_than_x )
# {True: 0, False: 1}

1 Comment

I appreciate the creativity of these! :) It could even scale up for more conditions and vars if certain ordering was followed but in that case I would have to accept that someone would kill me eventually (and rightly so).
1

Enhancing the idea of using a function:

def inc_if(condition, true_var, false_var):
    if condition:
        true_var += 1
    else:
        false_var += 1

    return (true_var, false_var)


B, C = inc_if(A > X, B, C)

This is quite readable because it can be read from left to right as "increment if A > X" followed by the variable that would be in the if clause and at last the variable from the else clause.

The variables need to be returned by the function and reassigned, unless global variables are used.

1 Comment

Good improvement, the reassignment is necessary as you point out. Sadly it also makes it computationally more expensive hence it seems that staying with the original is the only reasonable course of action.
1

If X varies across the conditionals but A, B, and C remain the same, you can refactor to a simple loop.

for X in (1, 2, 3, 5, 7, 13, 17, 23):
    if A > X:
        B += 1
    else:
        C += 1

Comments

0

this isn't one line, but you can increment each variable by the increment times the boolean expression

inc = 1
B += inc * (A > X)
C += inc * (A < X)

or you can use this

inc = 1
B += inc * (A > X); C += inc * (A < X)

1 Comment

Two tests instead of one, two assignment instead of one, two multiplications instead of none .... not an improvement IMO

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.