Is there a way to simplify bloc of if statements?

Question:

Is there a way to simplify this block of if statements?

    if ro<=1:
        F=1.23
    elif 1<ro<=1.05:
        F=1.24
    elif 1.05<ro<=1.1:
        F=1.25
    elif 1.1<ro<=1.12:
        F=1.26
    elif 1.12<ro<=1.16:
        F=1.27
    elif 1.16<ro<=1.19:
        F=1.28
    elif 1.19<ro<=1.21:
        F=1.29
    elif 1.21<ro<=1.24:
        F=1.3
    elif 1.24<ro<=1.28:
        F=1.31
    elif 1.28<ro<=1.32:
        F=1.32
    elif 1.32<ro<=1.37:
        F=1.34
    elif 1.37<ro<=1.43:
        F=1.35
    elif 1.43<ro<=1.51:
        F=1.37
    elif 1.51<ro<=1.62:
        F=1.39
    elif 1.62<ro<=1.78:
        F=1.42
    elif 1.78<ro<=2.06:
        F=1.45
    elif 2.06<ro<=2.74:
        F=1.49

Answers:

You can have a dictionary (or list) for the ranges and F-values so it’s simpler to read and debug:

ranges = {
    (0.0, 1.0): 1.23,
    (1.0, 1.05): 1.24,
    (1.05, 1.1): 1.25,
    (1.1, 1.12): 1.26,
    (1.12, 1.16): 1.27,
    (1.16, 1.19): 1.28,
    (1.19, 1.21): 1.29,
    (1.21, 1.24): 1.3,
    (1.24, 1.28): 1.31,
    (1.28, 1.32): 1.32,
    (1.32, 1.37): 1.34,
    (1.37, 1.43): 1.35,
    (1.43, 1.51): 1.37,
    (1.51, 1.62): 1.39,
    (1.62, 1.78): 1.42,
    (1.78, 2.06): 1.45,
    (2.06, 1.74): 1.49 # note: this range doesn't make sense
}

for (low, high), f_value in ranges.items():
    if low < ro <= high:
        F = f_value

But if you look at it from a time complexity perspective, you might be better of with a search tree structure.

Answered By: Yevhen Kuzmovych

First, you don’t need < operator since it is already filtered by elif(else).
So,

    if ro <= 1:
        F = 1.23
    elif ro <= 1.05:
        F = 1.24
    elif ro <= 1.1:
        F = 1.25
    elif ro <= 1.12:
        F = 1.26
    elif ro <= 1.16:
        F = 1.27
    elif ro <= 1.19:
        F = 1.28
    elif ro <= 1.21:
        F = 1.29
    elif ro <= 1.24:
        F = 1.3
    elif ro <= 1.28:
        F = 1.31
    elif ro <= 1.32:
        F = 1.32
    elif ro <= 1.37:
        F = 1.34
    elif ro <= 1.43:
        F = 1.35
    elif ro <= 1.51:
        F = 1.37
    elif ro <= 1.62:
        F = 1.39
    elif ro <= 1.78:
        F = 1.42
    elif ro <= 2.06:
        F = 1.45
    # elif ro <= 1.74:
    #     F = 1.49

has same result.
(I’m not sure what is expected from last condition).

And, you can create range-value table.

range_table: list[tuple[float, float]] = [
    (1.00, 1.23),
    (1.05, 1.24),
    (1.10, 1.25),
    (1.12, 1.26),
    (1.16, 1.27),
    (1.19, 1.28),
    (1.21, 1.29),
    (1.24, 1.30),
    (1.28, 1.31),
    (1.32, 1.32),
    (1.37, 1.34),
    (1.43, 1.35),
    (1.51, 1.37),
    (1.62, 1.39),
    (1.78, 1.42),
    (2.06, 1.45),
    (None, 1.49),
]

for range_, value in range_table:
    if range_ is None or ro <= range_:
        F = value
        break

If you are using Python 3.7 or later version, it can be done with dict, too. Because the order is matter, and Python 3.7+ versions guarantees dict‘s order by its creation.

range_table: dict[float, float] = {
    1.00: 1.23,
    1.05: 1.24,
    1.10: 1.25,
    1.12: 1.26,
    1.16: 1.27,
    1.19: 1.28,
    1.21: 1.29,
    1.24: 1.30,
    1.28: 1.31,
    1.32: 1.32,
    1.37: 1.34,
    1.43: 1.35,
    1.51: 1.37,
    1.62: 1.39,
    1.78: 1.42,
    2.06: 1.45,
    None: 1.49,
}

for range_, value in range_table.items():
    if range_ is None or ro <= range_:
        F = value
        break
Answered By: Boseong Choi
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.