Избегайте вычисления одного и того же выражения дважды в понимании списка
Я использую функцию в понимании списка и функцию if:
new_list = [f(x) for x in old_list if f(x) !=0]
Меня раздражает, что выражение f(x)
вычисляется дважды в каждом цикле.
Есть ли способ сделать это более чистым способом? Что-то вроде сохранения значения или включения оператора if в начале понимания списка.
4 ответа
Вычислите результаты заранее и переберите их
new_list = [x for x in map(f, old_list) if x !=0]
Более того, поскольку map вычисляет результат для элемента при обращении к элементу, это всего лишь один цикл.
Вы можете использовать выражение генератора (чтобы избежать создания ненужного списка) внутри вашего списка:
new_list = [fx for fx in (f(x) for x in old_list) if fx != 0]
начиная с Python 3.8 вы сможете сделать это:
new_list = [fx for x in old_list if (fx := f(x)) != 0]
В Python 3.8 у нас будет "оператор моржа", и мы сможем это сделать!
[y for x in old_list if (y := f(x)) != 0]
Вы могли бы использовать filter
чтобы удалить результаты:
def f (x):
return x * 2
old_list = [0, 1, 2, 3]
new_list = filter(lambda x: x != 0, [f(x) for x in old_list])
for x in new_list:
print(x)
Посмотрите, как это работает здесь.
В качестве альтернативы вы можете запомнить функцию, чтобы избежать необходимости вычислять один и тот же результат дважды:
def f (x):
return x * 2
def memoize(f):
memo = {}
def helper(x):
if x not in memo:
print("Computing result for %s" % x)
memo[x] = f(x)
return memo[x]
return helper
memF = memoize(f)
old_list = [0, 1, 2, 3]
new_list = [memF(x) for x in old_list if memF(x) != 0]
for x in new_list:
print(x)
Который доступен здесь.