why lambda x: x % 2 means odd number - python

>>> fibonacci = [0,1,1,2,3,5,8,13,21,34,55]
>>> odd_numbers = list(filter(lambda x: x % 2, fibonacci))
>>> print(odd_numbers)
[1, 1, 3, 5, 13, 21, 55]
>>> even_numbers = list(filter(lambda x: x % 2 == 0, fibonacci))
>>> print(even_numbers)
[0, 2, 8, 34]
why not like this: lambda x: x % 2 == 1

It is because x % 2 will be read as a boolean and 0 is false and 1 is true (like every number different of 0).
You can try it with
print (True == 1) # True
print (False == 0) # True
Try it online!

In boolean context, non-zero is true (and zero is false). Your version is quite legal as well, it's mostly save some typing.

It is because (x % 2) would return 1 if x is divisible by 2 else 0.Now in Boolean context
1 is for True and 0 is for False.Therefore, in filter function we use only x%2 for getting the odd numbers, because it will give 0(False) if it is divisible by 2 else 1(True).

This behaviour is due to filter function rather than lambda here.
filter definition:
As the name suggests, filter creates a list of elements for which a function returns true.
filter(func, iterable) ---> func is the function which will be executed on iterable.
So now lets see how will filter work in this case.
fibonacci = [0,1,1,2,3,5,8,13,21,34,55]
odd_numbers = list(filter(lambda x: x % 2, fibonacci))
# For each element in fibonacci:
# x = fibonacci[0]
# lambda x: x % 2 will return 0 which is equivalent to False
# Now filter will ignore this as the result of filter is False
# Next Iteration: x = fibonacci[1]
# lambda x: x % 2 will return 1 which is equivalent to True
# So filter will get this value
# therefore, odd_numbers = [1]
# So on and so forth.
Hope it helps.

Related

python reduce function returns false for check same element in a list [duplicate]

This question already has answers here:
How does reduce function work?
(9 answers)
Closed 3 years ago.
>>> reduce(lambda x,y: x == y, [2,2,2,2,2])
False
I want to check every element in a list if they are the same and I thought this would do the trick, apprarently not. Can you some explain why it returns false and how should I fix it?
If you look at the docs,
reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5)
So, a smaller example reduce(lambda x,y: x == y, [2,2,2]) would be (2==2)==2 would be False
The first application of the lambda function is 2 == 2, which yields True. The next application is True == 2, which is False. Finally, the last two applications of the lambda do False == 2, which is again False.
If the list has length >= 1, I would do:
all(lst[0] == x for x in lst)
In the lambda function you gives, x is the accumulated value, and y is each element in the array.
x: 2, y: 2, lambda returns True
x: True, y: 2, lambda returns False
...
x: False, y: 2, lambda returns False
To fix it, you could simple use len(set(arr)) == 1 to see if there is only one unique element in this array.
A simpler way to do this would be to check if the number of distinct elements in the list is 1
len(set([2,2,2,2,2]))==1
If you print the value of x and y during the reduce operation:
def f(x,y):
print 'x=',x,'y=',y
return x==y
print reduce(f, [2,2,2,2,2])
it outputs :
x= 2 y= 2
x= True y= 2 #x contains True because it is the result of (x==y) hence 2==2
x= False y= 2 #x contains False because it is the result of (x==y) hence True==2
x= False y= 2 #same reason
False
To avoid this behavior you could specify an initial element that contains the result of the reduction and the value of the previous element.
Something like
def f(x,y):
print 'x=',x, 'y=', y
return (x[1]==None or (x[0] and x[1]==y), y)
print reduce(f, [2,2,2,2,2], (True,None))
This time it outputs :
x= (True, None) y= 2
x= (True, 2) y= 2
x= (True, 2) y= 2
x= (True, 2) y= 2
x= (True, 2) y= 2
(True, 2)
In a compressed lambda form it boils down to:
reduce(lambda x,y: (x[1]==None or (x[0] and x[1]==y), y), list, (True,None))[0]
Try it
l = [2,2,2,2,2]
print reduce(lambda x,y: (x[1]==None or (x[0] and x[1]==y), y), l, (True,None))[0]
l = [2,2,3,2,2]
print reduce(lambda x,y: (x[1]==None or (x[0] and x[1]==y), y), l, (True,None))[0]
True
False

Attempt to use reduce

alternatively using reduce
def is_prime_no(x): #"True" represents Prime
np = 1
if x < 2:
np = 0
else:
for i in range(3, x): #int(math.sqrt(n))
if x % i == 0:
np =0
return np
print is_prime_no(12)
def prime_check(a,b):
if is_prime_no(a) == 1 and is_prime_no(b) == 1:
return 1
else:
return 0
print "prime check result ", prime_check(13,17)
From here does not work
def list_prime_check(values):
return reduce(prime_check, values)
print "Check items in list are prime ", list_prime_check([13,17,19])
Returns 0 but not 1 - i being true
Remember that in reduce(lambda a, b: ..., ...), the return value of the function becomes the new a. Therefore, you have:
reduce(prime_check, [13, 17, 19]) # =>
prime_check(13, 17) # => 1 =>
reduce(prime_check, [1, 19]) # uhh, what? =>
prime_check(1, 19) # uh-oh...
This particular instance of the problem is better served with all:
all(...)
all(iterable) -> bool
Return True if bool(x) is True for all values x in the iterable.
If the iterable is empty, return True.
Used like so:
>>> all([is_prime_no(x) for x in [13, 17, 19]])
True

Repeat function python

I'm stuck at higher-order functions in python. I need to write a repeat function repeat that applies the function f n times on a given argument x.
For example, repeat(f, 3, x) is f(f(f(x))).
This is what I have:
def repeat(f,n,x):
if n==0:
return f(x)
else:
return repeat(f,n-1,x)
When I try to assert the following line:
plus = lambda x,y: repeat(lambda z:z+1,x,y)
assert plus(2,2) == 4
It gives me an AssertionError. I read about How to repeat a function n times but I need to have it done in this way and I can't figure it out...
You have two problems:
You are recursing the wrong number of times (if n == 1, the function should be called once); and
You aren't calling f on the returned value from the recursive call, so the function is only ever applied once.
Try:
def repeat(f, n, x):
if n == 1: # note 1, not 0
return f(x)
else:
return f(repeat(f, n-1, x)) # call f with returned value
or, alternatively:
def repeat(f, n, x):
if n == 0:
return x # note x, not f(x)
else:
return f(repeat(f, n-1, x)) # call f with returned value
(thanks to #Kevin for the latter, which supports n == 0).
Example:
>>> repeat(lambda z: z + 1, 2, 2)
4
>>> assert repeat(lambda z: z * 2, 4, 3) == 3 * 2 * 2 * 2 * 2
>>>
You've got a very simple error there, in the else block you are just passing x along without doing anything to it. Also you are applying x when n == 0, don't do that.
def repeat(f,n,x):
"""
>>> repeat(lambda x: x+1, 2, 0)
2
"""
return repeat(f, n-1, f(x)) if n > 0 else x

Is it possible to use for loops inside print statement in Python

Can I use print elements in a for loop with some conditions ?
Actually I have this block of code :
sum = 0
for i in range(1,1000):
if i%3 == 0 or i%5 == 0 :
sum+=i
print(sum)
and I want to convert it in a single line of code.
Any help would be greatly appreciated.
You can use a generator expression:
print(sum(i for i in range(1,1000) if i%3 == 0 or i%5 == 0))
Note that I'm using the built-in function sum() here, which is different than you variable sum (in general you shouldn't use that as a name since it shadows the built-in function).
Using reduce and lambda:
>>> reduce( lambda x,y: x +y, [i for i in range(1000) if i % 3 == 0 or i % 5 == 0 ])
233168
>>>
Or If you want variable condition:
>>> def sum_it(Range, Divisible_by):
... return sum([[0, i][any([i % n == 0 for n in Divisible_by])] for i in range(Range)])
...
>>> sum_it(1000, [3,5])
233168
>>> sum_it(1000, [3,6])
166833
>>>

Find minimum values in a python 3.3 list

For example:
a=[-5,-3,-1,1,3,5]
I want to find a negative and a positive minimum.
example:
negative
print(min(a)) = -5
positive
print(min(a)) = 1
For getting minimum negative:
min(a)
For getting minimum positive:
min(filter(lambda x:x>0,a))
>>> a = [-5,-3,-1,1,3,5]
>>> min(el for el in a if el < 0)
-5
>>> min(el for el in a if el > 0)
1
Special handling may be required if a doesn't contain any negative or any positive values.
x = [-5,-3,-1,1,3,5]
# First min is actual min, second is based on absolute
sort = lambda x: [min(x),min([abs(i) for i in x] )]
print(sort(x))
[-5, 1]
[Program finished]
Using functools.reduce
>>> from functools import reduce
>>> a = [-5,-3,-1,2,3,5]
>>> reduce(lambda x,y: x if 0 <= x <=y else y if y>=0 else 0, a)
2
>>> min(a)
-5
>>>
Note: This will return 0 if there are no numbers >= 0 in the list.

Categories

Resources