what is this saying in python - python

map(tuple, map(lambda row: [float(row[0]), int(row[1]), parse(row[2])], res))
Can someone help me with the syntax here? I'm trying to understand specifically what tuple and lambda is referring to.

If it's easier to follow you could rewrite this a few times, from
map(tuple, map(lambda row:
[float(row[0]), int(row[1]), parse(row[2])], res))
to
map(lambda row: (float(row[0]), int(row[1]), parse(row[2])), res)
to
[(float(row[0]), int(row[1]), parse(row[2])) for row in res]
That doesn't really answer your question, but I thought it was easier to read ;)

tuple() is a constructor for a "tuple" object, that can convert a list (or other sequence object) to a tuple.
For example:
>>> a = [1, 2, 3]
>>> a
[1, 2, 3]
>>> tuple(a)
(1, 2, 3)
When used in your example, it converts the result of each lambda expression from a list to a tuple. It seems a bit redundant, because the following should be equivalent:
map(lambda row: (float(row[0], int(row[1], parse(row[2])), res)
Note the use of () parentheses instead of [] square brackets which creates a tuple rather than a list.

Related

How to write Inline/Lambda for appending or not appending to a list

I feel this a noob question but I haven't used lambda functions that much and I couldn't find what I needed online.
I wanted to write a lambda function which takes a series as an input, and returns a list without any 'None's in it
Basically I want a lambda function for the followinf function:
def get_path(x):
toRet = []
for item in x.tolist():
if item is not None:
toret.append(item)
return toRet
Is it possible to get an inline lambda function which does what get_path() does.
Yes I do know that I can do the following:
lambda x: get_path(x)
It solves the problem but I would really love to know how to make an inline function for this.
You don't even need lambda functions here.
toRet = [item for item in x.tolist() if item is not None]
You can also use filter for example, which looks neater
toRet = list(filter(None, x.tolist()))
get_path = lambda x: [ elem for elem in x.tolist() if not elem]
As others have pointed out, you can use filter() but be careful of what function you provide for the filter-check.
If function is None , the identity function is assumed, that is, all elements of iterable that are false are removed.
list(filter(None, something)) won't work correctly because it will filter out False-ish values too, not just None. Example:
>>> mylist = [1, 2, 3, 0, None, '', tuple(), 'last']
>>> list(filter(None, mylist)) # not the expected behaviour
[1, 2, 3, 'last']
OP had an explicit if item is not None check, rather than just if item - so the two are not equivalent. Only None needs to be filtered out. To get the correct filtering behaviour, provide an actual check for the function provided to filter:
>>> list(filter(lambda i: i is not None, mylist))
[1, 2, 3, 0, '', (), 'last']
Replace mylist with x.tolist(). And when you put that into a lambda, it gets messy:
get_path = lambda x: list(filter(lambda i: i is not None, x.tolist()))
Instead of all that, the list comprehension option is better:
get_path = lambda x: [i for i in x.tolist() if i is not None]
with an explicit is not None check.

Python function that returns the value at index 0?

Does the Python standard library have a function that returns the value at index 0? In other words:
zeroth = lambda x: x[0]
I need to use this in a higher-order function like map(). I ask because I believe it's clearer to use a reusable function rather than define a custom one - for example:
pairs = [(0,1), (5,3), ...]
xcoords = map(funclib.zeroth, pairs) # Reusable
vs.
xcoords = map(lambda p: p[0], pairs) # Custom
xcoords = [0, 5, ...] # (or iterable)
I also ask because Haskell does have such a function Data.List.head, which is useful as an argument to higher-order functions:
head :: [a] -> a
head (x:xs) = x
head xs = xs !! 0
xcoords = (map head) pairs
You need to use operator.itemgetter
>>> import operator
>>> pairs = [(0,1), (5,3)]
>>> xcoords = map(operator.itemgetter(0), pairs)
>>> xcoords
[0, 5]
In Python3, map returns a map object, hence you need a list call over it.
>>> list(map(operator.itemgetter(0), pairs))
[0, 5]
The most Pythonic approach would probably to use operator.itemgetter(0). It returns just such a function.
Another approach would be to call obj.__getitem__ directly. It's less Pythonic because it explicitly calls special method names, instead of allowing Python to infer what to call internally.
With a list comprehension:
>>> pairs = [(0,1), (5,3)]
>>> xcoords = [ t[0] for t in pairs ]
>>> xcoords

map,lambda and append.. why doesn't it work?

So I'm trying to do this.
a = []
map(lambda x: a.append(x),(i for i in range(1,5)))
I know map takes a function but so why doesn't it append to the list? Or is append not a function?
However printing a results to a still being empty
now an interesting thing is this works
a = []
[a.append(i) for i in range(5)]
print(a)
aren't they basically "saying" the same thing?
It's almost as if that list comprehension became some sort of hybrid list-comprehension function thing
So why doesn't the lambda and map approach work?
I am assuming you are using Python 3.x , the actual reason why your code with map() does not work is because in Python 3.x , map() returns a generator object , unless you iterate over the generator object returned by map() , the lambda function is not called . Try doing list(map(...)) , and you should see a getting filled.
That being said , what you are doing does not make much sense , you can just use -
a = list(range(5))
append() returns None so it doesn't make sense using that in conjunction with map function. A simple for loop would suffice:
a = []
for i in range(5):
a.append(i)
print a
Alternatively if you want to use list comprehensions / map function;
a = range(5) # Python 2.x
a = list(range(5)) # Python 3.x
a = [i for i in range(5)]
a = map(lambda i: i, range(5)) # Python 2.x
a = list(map(lambda i: i, range(5))) # Python 3.x
[a.append(i) for i in range(5)]
The above code does the appending too, however it also creates a list of None values as the size of range(5) which is totally a waste of memory.
>>> a = []
>>> b = [a.append(i) for i in range(5)]
>>> print a
[0, 1, 2, 3, 4]
>>> print b
[None, None, None, None, None]
The functions map and filter have as first argument a function reference that is called for each element in the sequence (list, tuple, etc.) provided as second argument AND the result of this call is used to create the resulting list
The function reduce has as first argument a function reference that is called for first 2 elems in the sequence provided as second argument AND the result is used together with the third elem in another call, then the result is used with the fourth elem, and so on. A single value results in the end.
>>> map(lambda e: e+10, [i for i in range(5)])
[10, 11, 12, 13, 14]
>>> filter(lambda e: e%2, [i for i in range(5)])
[1, 3]
>>> reduce(lambda e1, e2: e1+e2, [i for i in range(5)])
10
Explanations:
map example: adds 10 to each elem of list [0,1,2,3,4]
filter example: keeps only elems that are odd of list [0,1,2,3,4]
reduce example: add first 2 elems of list [0,1,2,3,4], then the result and the third elem of list, then the result and fourth elem, and so on.
This map doesn't work because the append() method returns None and not a list:
>>> a = []
>>> type(a.append(1))
<class 'NoneType'>
To keep it functional why not use reduce instead?
>>> from functools import reduce
>>> reduce(lambda p, x: p+[x], (i for i in range(5)), [])
[0, 1, 2, 3, 4]
Lambda function will not get triggered unless you wrap the call to map function in list() like below
list(map(lambda x: a.append(x),(i for i in range(1,5))))
map only returns a generator object which needs to be iterated in order to create a list. Above code will get the lambda called.
However this code does not make much sense considering what you are trying to achieve

Convert from tuple to string, untuplify

def untuplify(tpl):
return map(lambda x: str(x), tpl)
I can't get the output for untuplify((1, 2, 3, 4, 5)) which is 12345
Use str.join():
>>> def untuplify(tpl):
... return "".join(map(str, tpl))
...
>>> untuplify((1,2,3,4))
'1234'
>>>
The reason you're getting unexpected output is because map() returns a list. str.join() is the canonical way of joining strings from a sequence into a single string.

Python: how to create a function pointer with a set argument?

My problem:
Given the following:
def foo(a,b)
I am trying to call the python 'map' function while passing in a list for 'a' but use a set value for 'b.'
Another relevant fact is that 'b' is user input and thus, I cannot use the syntax:
def foo(a,b='default value')
I want my 'map' call to look like this:
map(foo_wrapper,list_for_a)
where 'foo_wrapper' is some function that takes in 'a' but uses the user specified 'b.'
I don't know whether function pointers can be specified this way and suspect that they cannot.
My solution to this problem uses globals, so if there's a more elegant way and the above is impossible, I will mark that as the answer as well.
Here is my solution in a nutshell:
b = ''
def foo(a,b):
print b,a
def foo_wrapper(a):
foo(a,b)
def main():
if sys.argv[1]:
a = ['John', 'Jacob', 'Jingle all the way']
global b
b = sys.argv[1]
map(foo_wrapper,a)
There may be a typo or two in the above; I am simplifying the problem from what I actually need to do.
Thanks for the replies!
You can use functools.partial() for this purpose:
from functools import partial
def f(a, b):
return a + b
x = range(10)
print map(partial(f, b=3), x)
prints
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
You want something akin to currying. You can just use lambda here:
map(lambda x: f(x,3), a)
Use a list comprehension or a generator expression
[f(x, your_set) for x in your_list]
If you don't need a list as a result, but just a lazy evaluated iterator, you can use a generator expression (or if you meant Python 3's map).
(f(x, your_set) for x in your_list)
Edit:
For your functions that would be:
L = ['John', 'Jacob', 'Jingle all the way']
[foo(a, b=b) for a in L]
List comprehensions are a syntax sugar to replace uses of map with lambda. If you have one of the following:
L2 = map(lambda arg: f(arg) + arg, L1)
L2 = map(lambda (x,y): x + y, L1)
L2 = map(lambda <arg>: <expression>, L1)
They can be rewritten as list comprehensions:
L2 = [f(arg) + arg for arg in L1]
L2 = [x + y for x, y in L1]
L2 = [<expression> for <arg> in L1]
Generator expressions are similar, but instead of a list they return a lazy iterator, and are written with parens instead of square brackets. (And because map in Python 3 is changed to not return lists, there its equivalent is a generator expression.) Sometimes a list is not need, for example when you want to do:
','.join(map(lambda x: x.upper(), L))
The equivalent list comprehension is:
','.join([x.upper() for x in L])
But you actually don't need a list, so you can simply do:
','.join(x.upper() for x in L)

Categories