Создание лямбда-функции Python из последовательности строк

У меня есть список из m элементов и n разных чисел, которые отображаются в списке строк. Список выглядит следующим образом:

eq = ['12', '2', '3', '-123', '-1', 'X']

Обратите внимание: X представляет константу 1, отличную от переменной 1. Я хочу, чтобы иметь возможность преобразовать это в лямбда-функцию, которая принимает список x и действует, как этот список суммируется вместе. Для нашего примера функция была бы

f(x) = x[1]*x[2] + x[2] + x[3] - x[1]*x[2]*x[3] - x[1] + 1

Я знаю, как это сделать с нормальной функцией, но я хотел заставить ее работать с лямбдой и ударить по стене. Любая помощь будет оценена!

Вот функция, которая работает для проблемы:

def evaluateList(x, lst):
 num = 0
 for term in lst:
 if term[0] == "X":
 num += 1
 elif term[0] == "-":
 num -= reduce(lambda x,y: x*y, [x[int(y)-1] for y in term[1:]])
 else:
 num += reduce(lambda x,y: x*y, [x[int(y)-1] for y in term])
 return num
4 ответа

Очевидно, что я рекомендую реализацию def:

from functools import reduce

eq = ['12', '2', '3', '-123', '-1', 'X']
x = [n for n in range(100)]

# Using an auxiliary function
def evaluate(n):
 if n == "X":
 return 1
 elif n[0] == "-":
 return reduce(lambda x, y: x * y, [x[int(y) - 1] for y in n[1:]])
 else:
 return reduce(lambda x, y: x * y, [x[int(y) - 1] for y in n])

print(sum(map(evaluate, eq)))

# As a pure lambda:

evaluate_lambda = lambda n: sum(map((lambda n: 1 if n == 'X' else (reduce(lambda x, y: x * y, [x[int(y) - 1] for y in n[1:]]) if n[0] == "-" else reduce(lambda x, y: x * y, [x[int(y) - 1] for y in n]))), eq))

print(evaluate_lambda(eq))


Вы можете использовать functools.reduce дважды, хотя результат не очень чистый:

from functools import reduce
from operator import sub, add
eq = ['12', '2', '3', '-123', '-1', 'X']
_x = [6, 4, 1, 4, 5, 2, 4, 23, 2, 4]
final_result = reduce(lambda x, y:[add, sub][y.startswith('-')](
 reduce(lambda c, d:c*d, [_x[int(i)] for i in x]) if x in eq else x, 
 reduce(lambda c, d:c*d, [_x[int(i)] for i in (y[1:] if y.startswith('-') else y)] if y != 'X' else [1])
 ), eq)
print(final_result)
x = _x
print(x[1]*x[2] + x[2] + x[3] - x[1]*x[2]*x[3] - x[1] + 1)

Вывод:

-10
-10

Но опять же, предопределенная функция намного легче читать и масштабировать.

Кроме того, немного короче, с sum:

new_result = sum([1, -1][i.startswith('-')]*reduce(lambda x, y:x*y, [1] if i == 'X' else [x[int(c)] for c in (i[1:] if i.startswith('-') else i)]) for i in eq)


что немного уродливый, но он работает

from operator import mul
a = lambda eq: sum([reduce(mul, [int(x) if x.isdigit() else [1,-1][x=='-'] for x in s]) for s in eq])


print(a(['12', '2', '3', '-123', '-1', 'X'])) # outputs 1
print(a(['126', '32', '3', '-2', 'X'])) # outputs 20

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


Я думаю, что это достаточно просто:

from operator import mul
from functools import reduce
prod = lambda L: reduce(mul, L, 1)
evaluateList = lambda(x, eq): sum(
 1 if expr == 'X' 
 else prod(-1 if i == '-' 
 else x[int(i)] 
 for i in expr) 
 for expr in eq)

licensed under cc by-sa 3.0 with attribution.