Reputation: 522
I have a list of m elements and n different numbers that appear in a list of strings. The list follows the following format example
eq = ['12', '2', '3', '-123', '-1', 'X']
Note, X represents the constant 1, other than the variable 1. I want to be able to convert this to a lambda function that takes in a list x and acts like this list was summed together. For our example the function would be
f(x) = x[1]*x[2] + x[2] + x[3] - x[1]*x[2]*x[3] - x[1] + 1
I know how to do this with a normal function, but I wanted to get it to work with a lambda and hit a wall. Any help would be appreciated!
Here is the function that works for the problem:
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
Upvotes: 2
Views: 3088
Reputation: 1281
that's a bit ugly but it works
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: of course this is just a game. always use the most readable function
Upvotes: 2
Reputation: 71461
You can use functools.reduce
twice, although the result is not very clean:
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)
Output:
-10
-10
But again, a predefined function is much easier to read and scale.
Also, slightly shorter, with 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)
Upvotes: 3
Reputation: 1648
Clearly I recommend the def
implementation:
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))
Upvotes: 3
Reputation: 13820
I think this is simple enough:
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)
Upvotes: 3