Как сделать более компактную запись условия?

Рейтинг: 2Ответов: 4Опубликовано: 06.05.2023

Вот мой код:

def is_odd_heavy(arr):
    even_arr = [x for x in arr if x%2==0]
    odd_arr = [x for x in arr if x%2!=0]

    if len(odd_arr)==0:
        return False
    elif len(even_arr)==0:
        return True

    return min(odd_arr)>max(even_arr)

Вопрос: Возможно ли заменить громоздкое условие в середине на более компактное?

Ответы

▲ 2Принят
return bool(odd_arr and (not even_arr or min(odd_arr) > max(even_arr)))

Т.е. если первый список непустой и либо второй список пустой, либо условие соблюдается

Еще можно (в каком-то смысле) упростить следующим образом

even_arr = sorted(x for x in arr if x%2==0)
odd_arr = sorted(x for x in arr if x%2!=0)

return odd_arr[:1] > even_arr[-1:]

Ну или так, чтобы не увеличивать временную сложность

max_even = max(((x,) for x in arr if x % 2 == 0), default=())
min_odd = min(((x,) for x in arr if x % 2 != 0), default=())

return min_odd > max_even

Сравнение кортежей / списков дает требуемый вам результат.

[]  > []   = False
[]  > [x]  = False
[x] > []   = True
[x] > [y]  = x > y
▲ 5
def is_odd_heavy(arr):
    even_arr = [x for x in arr if x % 2 == 0]
    odd_arr = [x for x in arr if x % 2 != 0]

    return False if len(odd_arr) == 0 else True if len(even_arr) == 0 else min(odd_arr) > max(even_arr)

# Тестовые примеры
print(is_odd_heavy([1, 3, 5, 7, 9]))  # True
▲ 4

Воспользуемся тем фактом, что операторам min и max можно задать значение по умолчанию в случае пустого списка или итератора, который подается им на обработку. Во время итерации по четным и нечетным числам одновременно вычисляем min и max или None, если числа не найдены. Далее отрабатываем три комбинации. При этом не создаются промежуточные списки, а используются генераторы, что экономит память и работает чуть быстрее.

def is_odd_heavy(arr):
    match (
        _min := min((x for x in arr if x % 2 != 0), default=None),
        _max := max((x for x in arr if x % 2 == 0), default=None)
    ):
        case (None, _):
            return False
        case (_, None):
            return True
        case _:
            return (_min > _max)
▲ 3

Можно сами условия сделать покороче:

Вместо

if len(odd_arr)==0:

так:

if not odd_arr:

И вместо

elif len(even_arr)==0:

так:

if not even_arr: