High Order Map Function with Lambda Expression Python - python

I'm trying to write a higher order function that will take 2 lambda expressions and a list and will return the result. I have my code below.
#Square
square = lambda x:x ** 2
#Mod_2
mod_2 = lambda x:x % 2
def map(f,x):
return f(x)
It looks very simple, and should be. This is the error I get:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "main.py", line 8, in map
return f(x)
File "main.py", line 2, in <lambda>
square = lambda x:x ** 2
TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'int'
Here's what the results should be:
>>> map(square, [1, 2, 3, 4])
[1, 4, 9, 16]
>>> map(square, [])
[]
>>> map(mod_2, range(1, 11))
[1, 0, 1, 0, 1, 0, 1, 0, 1, 0]
This is NOT homework, and is simply and way to understand higher order functions better. Also, this is not a repeat of any other submission because this is fixing MY code, not how to do the problem itself. If it needs rethinking, please reply and tell me how. Thank you!

Use a list comprehension:
def map(f,x):
return [f(i) for i in x]
You can use a lambda here too:
map = lambda f, x: [f(i) for i in x]
Or just use the map() built-in.

map() is a built-in function. Why are you redefining it? Delete def map().
#Square
square = lambda x: x**2
#Mod_2
mod_2 = lambda x:x % 2
r1 = list(map(square, [1, 2, 3, 4]))
r2 = list(map(mod_2, range(1, 11)))

Related

How do you round() a map function in python?

I am trying to do this,
print(list(round(map(radius, cirumfrence), 1)))
but it comes up with this error:/
print(list(round(map(radius, cirumfrence), 1)))
TypeError: type map doesn't define __round__ method
Anyone know what the problem is?
Thanks!
Here is the whole code.
cirumfrence = [2.7, 69, 7, 2]
radius = lambda circ: ((circ)/2*math.pi)
print(list(map(round(radius, cirumfrence))))
I would use a list comprehension:
cirumfrence = [2.7, 69, 7, 2]
radius = lambda circ: ((circ)/2*math.pi)
new_lst = [round(radius(x),2) for x in cirumfrence]
Output:
[4.24, 108.38, 11.0, 3.14]

Python: How to write this code from python shell into a function?

What's happening here is that the first and second element of every tuple are getting multiplied, and it adds all of the products in the end. I know how to enter it in the Python shell, but how do I write it out as a function? Thanks for the help.
>>> x = [(70.9, 1, 24.8),
(15.4, 2, 70.5),
(30.0, 3, 34.6),
(25.0, 4, 68.4),
(45.00, 5, 99.0)]
>>> result = (a[0]*a[1] for a in x)
>>> sum(result)
>>> 516.7
Create the function:
def my_func(x):
result = (a[0]*a[1] for a in x)
return sum(result)
Call the function:
x = [(70.9, 1, 24.8),
(15.4, 2, 70.5),
(30.0, 3, 34.6),
(25.0, 4, 68.4),
(45.00, 5, 99.0)]
my_func(x)
Result will be 516.7
using numpy packege dot product also we can archive this easily
import numpy as np
x = [(70.9, 1, 24.8),(15.4, 2, 70.5),(30.0, 3, 34.6),(25.0, 4, 68.4),(45.00, 5, 99.0)]
def func(list):
nmpyArray = np.array(list)
mul = np.dot(nmpyArray[:, 0], nmpyArray[:, 1])
print(mul)
return mul
func(x)

Reduce() after filter() in Python?

I have question about two functions in python: reduce() and filter().
Can we use reduce() after filter()?
I used boston datasets in sklearn.
x = load_boston()
x_target = x.target
xx = filter(lambda x: x > 20, x_target)
And it's working fine.
Next I want use reduce() function to sum up values in xx.
from functools import reduce
xxx = reduce(lambda x,y: x+y, xx)
I got error:
TypeError Traceback (most recent call last)
<ipython-input-64-062fcc861672> in <module>()
1 from functools import reduce
----> 2 xxx = reduce(lambda x,y: x+y, xx)
TypeError: reduce() of empty sequence with no initial value
Any suggestions?
Yes, you can use a filter() object in reduce() just fine:
>>> from functools import reduce
>>> values = range(10, 30)
>>> filtered = filter(lambda x: x > 20, values)
>>> reduce(lambda x, y: x + y, filtered)
225
However, a filter() object is an iterator; it will yield filtered values on demand, and when it reaches the end won't yield anything else. So you need to make sure you don't empty it before you pass it to reduce():
>>> filtered = filter(lambda x: x > 20, values)
>>> filtered
<filter object at 0x10ee64ac8>
>>> list(filtered)
[21, 22, 23, 24, 25, 26, 27, 28, 29]
>>> reduce(lambda x, y: x + y, filtered)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: reduce() of empty sequence with no initial value
Re-create the filter() object when you need to re-use it in multiple places.
That means the filter function returns an empty list over your list. Here you have an example:
sample = [2,3,4,5,6,7,8]
filter(lambda x: x%2 == 0, sample)
>>> [2, 4, 6, 8]
reduce(lambda x,y: x+y, filter(lambda x: x%2 == 0, sample))
>>> 20
So, your code should work.
This is python 2.7. Should be different in python 3+
EDIT: with python3
from functools import reduce
sample = [2,3,4,5,6,7,8]
f = filter(lambda x: x%2 == 0, sample)
reduce(lambda x,y: x+y, f)
>>> 20
Works the same way ; )

filter not returning the constructed or matched list [duplicate]

filter, map, and reduce work perfectly in Python 2. Here is an example:
>>> def f(x):
return x % 2 != 0 and x % 3 != 0
>>> filter(f, range(2, 25))
[5, 7, 11, 13, 17, 19, 23]
>>> def cube(x):
return x*x*x
>>> map(cube, range(1, 11))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>> def add(x,y):
return x+y
>>> reduce(add, range(1, 11))
55
But in Python 3, I receive the following outputs:
>>> filter(f, range(2, 25))
<filter object at 0x0000000002C14908>
>>> map(cube, range(1, 11))
<map object at 0x0000000002C82B70>
>>> reduce(add, range(1, 11))
Traceback (most recent call last):
File "<pyshell#8>", line 1, in <module>
reduce(add, range(1, 11))
NameError: name 'reduce' is not defined
I would appreciate if someone could explain to me why this is.
Screenshot of code for further clarity:
You can read about the changes in What's New In Python 3.0. You should read it thoroughly when you move from 2.x to 3.x since a lot has been changed.
The whole answer here are quotes from the documentation.
Views And Iterators Instead Of Lists
Some well-known APIs no longer return lists:
[...]
map() and filter() return iterators. If you really need a list, a quick fix is e.g. list(map(...)), but a better fix is often to use a list comprehension (especially when the original code uses lambda), or rewriting the code so it doesn’t need a list at all. Particularly tricky is map() invoked for the side effects of the function; the correct transformation is to use a regular for loop (since creating a list would just be wasteful).
[...]
Builtins
[...]
Removed reduce(). Use functools.reduce() if you really need it; however, 99 percent of the time an explicit for loop is more readable.
[...]
The functionality of map and filter was intentionally changed to return iterators, and reduce was removed from being a built-in and placed in functools.reduce.
So, for filter and map, you can wrap them with list() to see the results like you did before.
>>> def f(x): return x % 2 != 0 and x % 3 != 0
...
>>> list(filter(f, range(2, 25)))
[5, 7, 11, 13, 17, 19, 23]
>>> def cube(x): return x*x*x
...
>>> list(map(cube, range(1, 11)))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>> import functools
>>> def add(x,y): return x+y
...
>>> functools.reduce(add, range(1, 11))
55
>>>
The recommendation now is that you replace your usage of map and filter with generators expressions or list comprehensions. Example:
>>> def f(x): return x % 2 != 0 and x % 3 != 0
...
>>> [i for i in range(2, 25) if f(i)]
[5, 7, 11, 13, 17, 19, 23]
>>> def cube(x): return x*x*x
...
>>> [cube(i) for i in range(1, 11)]
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
>>>
They say that for loops are 99 percent of the time easier to read than reduce, but I'd just stick with functools.reduce.
Edit: The 99 percent figure is pulled directly from the What’s New In Python 3.0 page authored by Guido van Rossum.
As an addendum to the other answers, this sounds like a fine use-case for a context manager that will re-map the names of these functions to ones which return a list and introduce reduce in the global namespace.
A quick implementation might look like this:
from contextlib import contextmanager
#contextmanager
def noiters(*funcs):
if not funcs:
funcs = [map, filter, zip] # etc
from functools import reduce
globals()[reduce.__name__] = reduce
for func in funcs:
globals()[func.__name__] = lambda *ar, func = func, **kwar: list(func(*ar, **kwar))
try:
yield
finally:
del globals()[reduce.__name__]
for func in funcs: globals()[func.__name__] = func
With a usage that looks like this:
with noiters(map):
from operator import add
print(reduce(add, range(1, 20)))
print(map(int, ['1', '2']))
Which prints:
190
[1, 2]
Just my 2 cents :-)
Since the reduce method has been removed from the built in function from Python3, don't forget to import the functools in your code. Please look at the code snippet below.
import functools
my_list = [10,15,20,25,35]
sum_numbers = functools.reduce(lambda x ,y : x+y , my_list)
print(sum_numbers)
One of the advantages of map, filter and reduce is how legible they become when you "chain" them together to do something complex. However, the built-in syntax isn't legible and is all "backwards". So, I suggest using the PyFunctional package (https://pypi.org/project/PyFunctional/).
Here's a comparison of the two:
flight_destinations_dict = {'NY': {'London', 'Rome'}, 'Berlin': {'NY'}}
PyFunctional version
Very legible syntax. You can say:
"I have a sequence of flight destinations. Out of which I want to get
the dict key if city is in the dict values. Finally, filter out the
empty lists I created in the process."
from functional import seq # PyFunctional package to allow easier syntax
def find_return_flights_PYFUNCTIONAL_SYNTAX(city, flight_destinations_dict):
return seq(flight_destinations_dict.items()) \
.map(lambda x: x[0] if city in x[1] else []) \
.filter(lambda x: x != []) \
Default Python version
It's all backwards. You need to say:
"OK, so, there's a list. I want to filter empty lists out of it. Why?
Because I first got the dict key if the city was in the dict values.
Oh, the list I'm doing this to is flight_destinations_dict."
def find_return_flights_DEFAULT_SYNTAX(city, flight_destinations_dict):
return list(
filter(lambda x: x != [],
map(lambda x: x[0] if city in x[1] else [], flight_destinations_dict.items())
)
)
Here are the examples of Filter, map and reduce functions.
numbers = [10,11,12,22,34,43,54,34,67,87,88,98,99,87,44,66]
//Filter
oddNumbers = list(filter(lambda x: x%2 != 0, numbers))
print(oddNumbers)
//Map
multiplyOf2 = list(map(lambda x: x*2, numbers))
print(multiplyOf2)
//Reduce
The reduce function, since it is not commonly used, was removed from the built-in functions in Python 3. It is still available in the functools module, so you can do:
from functools import reduce
sumOfNumbers = reduce(lambda x,y: x+y, numbers)
print(sumOfNumbers)
from functools import reduce
def f(x):
return x % 2 != 0 and x % 3 != 0
print(*filter(f, range(2, 25)))
#[5, 7, 11, 13, 17, 19, 23]
def cube(x):
return x**3
print(*map(cube, range(1, 11)))
#[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
def add(x,y):
return x+y
reduce(add, range(1, 11))
#55
It works as is. To get the output of map use * or list

Python yield a list with generator

I was getting confused by the purpose of "return" and "yield"
def countMoreThanOne():
return (yy for yy in xrange(1,10,2))
def countMoreThanOne():
yield (yy for yy in xrange(1,10,2))
What is the difference on the above function?
Is it impossible to access the content inside the function using yield?
In first you return a generator
from itertools import chain
def countMoreThanOne():
return (yy for yy in xrange(1,10,2))
print list(countMoreThanOne())
>>>
[1, 3, 5, 7, 9]
while in this you are yielding a generator so that a generator within the generator
def countMoreThanOne():
yield (yy for yy in xrange(1,10,2))
print list(countMoreThanOne())
print list(chain.from_iterable(countMoreThanOne()))
[<generator object <genexpr> at 0x7f0fd85c8f00>]
[1, 3, 5, 7, 9]
if you use list comprehension then difference can be clearly seen:-
in first:-
def countMoreThanOne():
return [yy for yy in xrange(1,10,2)]
print countMoreThanOne()
>>>
[1, 3, 5, 7, 9]
def countMoreThanOne1():
yield [yy for yy in xrange(1,10,2)]
print countMoreThanOne1()
<generator object countMoreThanOne1 at 0x7fca33f70eb0>
>>>
After reading your other comments I think you should write the function like this:
def countMoreThanOne():
return xrange(1, 10, 2)
>>> print countMoreThanOne()
xrange(1, 11, 2)
>>> print list(countMoreThanOne())
[1, 3, 5, 7, 9]
or even better, to have some point in making it a function:
def oddNumbersLessThan(stop):
return xrange(1, stop, 2)
>>> print list(oddNumbersLessThan(15))
[1, 3, 5, 7, 9, 11, 13]

Categories

Resources