How to solve lambda() takes 1 positional argument but 2 were given - python

I have the following code snippet but it is giving me the type error above. What I basically wanted to do is add two to every element and reduct it to a single sum, but it didnt work. How can we achieve this??
import functools
list1 = [1,2,3,4]
result = functools.reduce(lambda x:x+2, list1)
print(result)
Update:
It works when I do the following though:
list1 = [1,2,3,4]
result = functools.reduce(lambda x,y:x+y, list1)
print(result)

reduce() requires a lambda function which takes 2 arguments.
The first argument is the collector.
But here, so that +2 is applied also on the first argument, you have to give the initial value 0.
import functools
list1 = [1,2,3,4]
result = functools.reduce(lambda acc, el: acc + el + 2, list1, 0)
print(result) ## sum([3, 4, 5, 6]) = 18
You basically want to do a normal summing reduce(lambda x, y: x + y, lst) => sum(lst)
and a map(lambda x: x + 2, l) which is expressed in a more pythonic way as a list comprehension:
l = [1, 2, 3, 4]
sum([x + 2 for x in l]) # most pythonic!
## 18
sum(map(lambda x: x + 2, l))
## 18
or:
import functools
l = [1, 2, 3 ,4]
result = functools.reduce(lambda x, y: x + y, [x + 2 for x in l])
result ## 18
or:
import functools
l = [1, 2, 3 ,4]
result = functools.reduce(lambda x, y: x + y, map(lambda x: x + 2, l))
result ## 18

The callable passed to the reduce function needs to take two arguments to aggregate the current result with the next item from the given iterable:
import functools
list1 = [1, 2, 3, 4]
result = functools.reduce(lambda x, y: x + y + 2, list1, 0)
print(result)
This outputs:
18

Related

Python mapped object becoming empty after being reduced

A = map(lambda x: x * 2, [1, 2])
z = reduce(lambda x, y: x + y, A)
print(z, list(A))
# outputs: 6 []
It's so confused that the canonical map reduce FP operation leads to the destructive end. What has happened beneath the surface?
map returns an iterator. Your reduce fully consumes that iterator, so there is nothing left afterwards. If you turn A into a list before the reduce, it works as expected:
A = list(map(lambda x: x * 2, [1, 2]))
z = reduce(lambda x, y: x + y, A)
print(z,A) #prints 6 [2, 4]

call lambda functions from list

If I have a list containing a lambda function, for example:
a = [lambda x: x * 2]
how could I call this lambda function to a list:
b = [1,2,3,4]
so that it could have the result as:
result = list(map(lambda x: x * 2, b))
and get:
[2,4,6,8]
Further, what if a contains two lambda functions, for example:
a = [lambda x:x * 2, lambda x: x-1]
How could I call these functions to list b without using for loop or list comprehension but use map()?
I hope someone could help me with it!
You can simply do
result = list(map(a[0], b))
# [2,4,6,8]
since the lambda function is the first element of a
For the second function it's the same thing
result = list(map(a[1], b))
If you want to apply all functions in one line
[list(map(a[i],b)) for i in range(len(a))]
#[[2, 4, 6, 8], [0, 1, 2, 3]]
You can iterate over the lambda functions in the list no matter how many elements stored in it:
a = [lambda x:x * 2, lambda x: x-1]
b = [1, 2, 3, 4]
for func in a:
# apply each function on b and turn the results to list:
print(list(map(func, b)))
If you want to store each result:
a = [lambda x:x * 2, lambda x: x-1]
b = [1, 2, 3, 4]
results = []
for func in a:
results.append(list(map(func, b)))
In the special case of a single lambda wrapped in a list, do
result = list(map(a[0], b))
But there are no special cases in python. So for the general case, you can either have a flat list:
result = [f(x) for f in a for x in b]
or a nested one:
result = [[f(x) for f in a] for x in b]
You can reverse the sort order of the lists by swapping the loops over a and b.
You can even go as far as using itertools.product to get the flat case (again with a and b interchangeable to change the order of the result):
result = [f(x) for f, x in itertools.product(a, b)]

Multiply every element of RDD with corresponding element in a list

for example:
x = RandomRDDs.normalRDD(sc, size=3, seed=0)
x is like this: [-1.3, -2.4, -4.5]
I want to multiply every element of x with a different number in a list [1, 2, 3] and add them to produce y.
here y equals -1.3*1 + -2.4*2 + -4.5*3
but i can only do this:
y = x.map(lambda i: i*2).reduce(lambda a, b: a+b)
here y = -1.3*2 + -2.4*2 + -4.5*2
how can i replace 2 in x.map(lambda i: i*2) with a diffrent number every time?
the final effect is like what we often do in python:
x = [-1.3, -2.4, -4.5]
w = [1, 2, 3]
y = sum(x*w)
or
sum([x[i]*w[i] for i in range(len(x))])
thanks a lot!
I would do this using zipWithIndex and map:
x = RandomRDDs.normalRDD(sc, size=3, seed=0)
w = sc.broadcast([1, 2, 3])
x.zipWithIndex().map(lambda v: v[0] * w.value[v[1]]).sum()
Or,
import operator
x.zipWithIndex().map(lambda v: v[0] * w.value[v[1]]).reduce(operator.add)

Python Reduce Math Equation

I am given a list of numbers a = [1, 2, 3, 4, 5, 6] and using only Python's reduce function, return a value. The value is calculated by:
(((...(a[0] + a[1]) * a[2] + a[3]) * a[4] + ...)
So in the above example where a = [1, 2, 3, 4, 5, 6], the answer should be ((1 + 2) * 3 + 4) * 5 + 6 = 71
I'm fairly new to Python and I'm trying to learn it:
reduce(lambda x,y: x * y, map(lambda x,y: x+y, numbers))
The tricky bit is, of course, that you have to alternate between two functions in reduce. Since you can't really keep track of the current position in the list1), in order to decide which operation to use, your best chance is to use an iterator that alternates between + and *.
You could use itertools.cycle to alternate between add and mul and use those in reduce
>>> import itertools, operator
>>> op = itertools.cycle([operator.add, operator.mul])
>>> a = [1, 2, 3, 4, 5, 6]
>>> reduce(lambda x, y: next(op)(x, y), a)
71
If you can't use those modules, you can make a generator expression alternating between + and * using lambdas in a ternary expression. The rest remains the same.
>>> op = ((lambda x,y:x+y) if i % 2 == 0 else (lambda x,y:x*y) for i in range(len(a)))
>>> a = [1, 2, 3, 4, 5, 6]
>>> reduce(lambda x, y: next(op)(x, y), a)
71
1) Well, you can, using enumerate(a), or zip(range(len(a)), a), if you prefer...
>>> a = [1, 2, 3, 4, 5, 6]
>>> reduce(lambda x, y: (y[0], x[1]+y[1]) if x[0]%2==0 else (y[0], x[1]*y[1]), enumerate(a))[1]
71
Or shorter, using tuple-unpacking in the lambdas, but this only works in Python 2.x:
>>> reduce(lambda (i,x),(j,y): (j, x+y) if i%2==0 else (j, x*y), enumerate(a))[1]
Improving the solution of Akash Patel, i have come up with this, with only reduce.
reduce(lambda acc,x: (acc+x[1] if x[0]%2 else acc*x[1]), enumerate(numbers), 1)
We need to add odd number of elements and multiply even number of elements with previous elements.
This was a tough problem because you wanted to use everything in reduce. So just use reduce twice!
reduce(lambda x, y: x + y, reduce(lambda x, y: (x[0], x[1] + y[1]) if y[0]%2==1 else (x[0], x[1]*y[1]) , enumerate(a)))

how to do mutation in python? by reordering the original list

def swap_numbers(x, x_index):
for num in x:
if x_index < len(x)-1:
x[:] = x[:x_index] + [x[x_index+1]] + [x[x_index]]+ x[x_index+2:]
elif x_index == len(x)-1:
x[:] = [x[-1]] + x[1:-1] + [x[0]]
so if I want to mutate a list lets say x = [1,2,3,4,5] and x_index = 2
what this function does is swap the number of the index we input with the follows number.
It should be like
>>> x = [1,2,3,4,5]
>>> swap_numbers(x,2)
>>> x
[1,2,4,3,5]
but mine is
>>> x = [1,2,3,4,5]
>>> swap_numbers(x,2)
>>> x
[1,2,3,4,5]
however it works if I make the first part of function
x[:] = [x[:x_index] + [x[x_index+1]] + [x[x_index]] + x[x_index+2:]]"
it will then become
>>> x = [1,2,3,4,5]
>>> swap_numbers(x,2)
>>> x
[[1,2,4,3,5]]
what should I do?
Maybe something like this:
def swap (l, i):
l [i], l [i + 1] = l [i + 1], l [i]
This yields:
>>> def swap (l, i): l [i], l [i + 1] = l [i + 1], l [i]
...
>>> a = [1, 2, 3, 4, 5]
>>> swap (a, 2)
>>> a
[1, 2, 4, 3, 5]
It depends what you want to do with an index error (the swap does not exist) but this works:
x = [1,2,3,4,5]
def swap_numbers(li, ind):
try:
li[ind],li[ind+1]=li[ind+1],li[ind]
except IndexError:
pass
swap_numbers(x,2)
print x
# [1, 2, 4, 3, 5]
This will just not do anything that cannot be done, like swap_numbers(x,5)

Categories

Resources