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]
Related
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
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)]
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)
I'm relatively new to the Python language. I'm aware of most of the basic functionality & theory, all the different classes of object and their behavior/properties etc.
Anyway, I was writing basic functions to explore different concepts in practice and get to know the language more intuitively. One in particular has left me vexed! Can anyone share any insight into why this result is not as expected?
Here is the code I ran:
test_list = [2, 4, 6]
def test_func(k):
global x, y, z
for n in k:
k[k.index(n)] = n * 2
x, y, z = k
return k
test_func(test_list)
print(test_list)
print(x)
print(y)
print(z)
I would have expected the result to be:
[4, 8, 12]
4
8
12
However, the actual result is as follows:
[8, 4, 12]
8
4
12
It seems that the first two items of the list have been swapped.
I can't see what could be causing this? If anyone can see what's happening here, please share the insight!
Thanks,
Oscar South
After first iteration you list look like [4,4,6] so k.index(4) return 0 index and multiple it by 2. So final result is [8,4,12].
I think you meant to do this:
test_list = [2, 4, 6]
def test_func(k):
global x, y, z
for i in range(len(k)):
k[i] = k[i] * 2
x, y, z = k
return k
You're mixing indexes with values, and using index() to find the position in an array is incorrect, most of all because you're modifying the list and you'll find the same elements again but in different positions, better use a range to iterate over the indexes and retrieve the values.
Also, using globals is not cool. In fact, the whole procedure should be written like a list comprehension instead - simple and idiomatic:
[2 * x for x in test_list]
=> [4, 8, 12]
In the first iteration the first element is changed to 4. In the second iteration the index of 4 is 0 not 1 as you expect.
Try this:
test_list = [2, 4, 6]
def test_func(k):
global x, y, z
l = list()
for n in k:
print(n, k.index(n))
l.append(n * 2)
x, y, z = l
return l
test_func(test_list)
print(test_list)
print(x)
print(y)
print(z)
You can condense the code into a list comprehension and unpacking:
test_list = [2, 4, 6]
def test_func(k):
global x, y, z
x, y, z = [i*2 for i in k]
return [x, y, z]
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)))