Python, я много повторяю, когда речь заходит о циклах, и должен быть лучший способ

Давайте скажем, что у меня есть три списка, и мне нужно перебирать их и делать некоторые вещи для содержимого.

Три списка: streaks_0, streaks_1 и streaks_2. Для каждого списка мне нужно использовать разные значения, относящиеся к каждому списку. Например, streak_0_num0s не будет работать в цикле streaks_1 for.

Есть ли способ сделать эти три для циклов в один или, по крайней мере, способ очистить это?

for number in streaks_0:
    if number == 0:
        streak_0_num0s += 1
    elif number != 0:
        streak_0_sum += number
streak_0_average = (streak_0_sum / (len(streaks_0) - streak_0_num0s))

for number in streaks_1:
    if number == 0:
        streak_1_num0s += 1
    elif number != 0:
        streak_1_sum += number
streak_1_average = (streak_1_sum / (len(streaks_1) - streak_1_num0s))

for number in streaks_2:
    if number == 0:
        streak_2_num0s += 1
    elif number != 0:
        streak_2_sum += number
streak_2_average = (streak_2_sum / (len(streaks_2) - streak_2_num0s))

Ответ 1

Почему бы не использовать функцию?

def get_average(streaks):
    streak_0_num0s = 0
    streak_0_sum = 0

    for number in streaks:
        if number == 0:
            streak_0_num0s += 1
        elif number != 0:
            streak_0_sum += number
    streak_0_average = (streak_0_sum / (len(streaks) - streak_0_num0s))
    print(streak_0_average)

get_average(streaks01)
get_average(streaks02)
get_average(streaks03)

Ответ 2

Ваш код может быть легко упрощен с помощью функции, подобной приведенной ниже:

def calculate_avg(lst):
    return sum(lst)/(len(lst)-lst.count(0))

или этот, если вы предпочитаете:

def calculate_avg(lst):
    return sum(lst) / len([l for l in lst if l != 0])

и вот небольшой пример использования:

streaks = [
    [1, 2, 3, 0, 0, 0, 0],
    [0, 0, 0, 4, 5, 6, 0],
    [0, 0, 6, 7, 8, 0, 0]
]

for index, streak in enumerate(streaks):
    print("avg(streak{})={}".format(str(index).zfill(2), calculate_avg(streak)))

Ответ 3

Напишите функцию, которую вы можете вызывать несколько раз:

def calculate_average(values):
    non_zeros = 0
    sum = 0

    for value in values:
        if value != 0:
            sum += value
            non_zeros += 1
    return sum / non_zeros

streak_0_average = calculate_average(streaks_0)
streak_1_average = calculate_average(streaks_1)
streak_2_average = calculate_average(streaks_2)

Ответ 4

Как уже говорили другие: когда вы обнаружите, что вы повторяете себя много раз: попытайтесь создать функцию, которую можно повторно использовать.

Однако всегда полезно взглянуть и посмотреть, действительно ли кто-то уже реализовал такую ​​функцию. В вашем случае вы можете использовать numpy.mean (numpy - сторонний модуль) или statistics.mean (statistics - встроенный модуль в python 3.4+).

Единственное, что они не делают по умолчанию, это исключение нулей, поэтому вы должны сделать это сами:

import numpy as np

def average(streaks):
    streaks = np.asarray(streaks)
    streaks_without_zeros = streaks[streaks != 0]
    return np.mean(streaks_without_zeros)

streaks_0 = [1, 2, 3, 4, 0, 1, 2, 3]
print(average(streaks_0))  # 2.2857142857142856

или

import statistics

def average(streaks):
    streaks_without_zeros = [streak for streak in streaks if streak != 0]
    return statistics.mean(streaks_without_zeros)

streaks_0 = [1, 2, 3, 4, 0, 1, 2, 3]
print(average(streaks_0))  # 2.2857142857142856