Using map function in python - python

If you have the following code, how exactly is it following the documentation: map(function, iterable,...)?
x = sorted(map(int, dat[0].split()))
Is int a function and if so, why isn't it expressed as such?

int is a constructor so it's callable so you can use it with map

In your case dat[0] is as string, and split() generates a list of strings, by splitting the input string at whitespaces.
Eg
"1 11".split()
returns
["1", "11"]
The map function has two input arguments:
The first argument is something which can be called (in Python you say it is a callable), eg a function. int is not realy a function but such a thing (Python slang: it is an object).
Eg int("3") return 3. So int when applied to a string tries to convert this string to an integer, and gives the integer value back.
The second argument is something you can iterate over, in your case it is a list.
If you then call the map function, the first argument is applied to all elements from the second argument.
So
map(int, ["1", "11"])
returns
[1, 11]
If you combine what I explained you understand that
map(int, "1 11".split())
returns
[1, 11]

When you ask "why isn't it expressed as such" I suppose you mean, why doesn't it have brackets like a function? The answer is that if you put the brackets in then you get what the function does instead of the function itself. Compare what happens when you enter int() versus int.

Think of it like this
def map( function, iterable ):
return ( function(x) for x in iterable )
In x = sorted(map(int, dat[0].split())) the function, int, is being named, not evaluated. This code provides a function object to the map function. The map function will evaluate the given function.

The syntax of map in the simplest form is:
map(func, sequence)
It will apply the function "func" on each element of the sequence and return the sequence. Just in case you don't know, int() is a function.
>>> int(2.34)
2
>>> int("2")
2
>>> a = ["1", "101", "111"]
>>> map(int, a)
[1, 101, 111]
Now, I will give you my implementation of map().
>>> for index in range(len(a)):
... a[index] = int(a[index])
...
>>> a
[1, 101, 111]
If you have understood the concept, let's take a step further. We converted the strings to int using base 10 (which is the default base of int() ). What if you want to convert it using base 2?
>>> a = ["1", "101", "111"]
>>> for index in range(len(a)):
... a[index] = int(a[index], 2) # We have an additional parameter to int()
...
>>> a
[1, 5, 7]
To get the same result using map(), we will use a lambda function
>>> a = ["1", "101", "111"]
>>> map(lambda x: int(x, 2), a)
[1, 5, 7]

Related

How to use index to get the value from the result of map function by Python 3?

I try this:
def test(x):
return x**2
a = map(test,[1,2,3])
If I get the value like this:
for i in a:
print(a)
I will get 1,4,9 and this works perfectly.
But if I do this: a[0]. The error will be raised.
I know it is because the result of map function is map class:
type(map(test,[1,2,3])) == <class 'map'>
which is not subsciptable.
So how can I use the index to get the value of the result of map function?
NOTE: This behavior is specific to python 3.
Convert the map object into a list object:
a = list(map(test,[1,2,3]))
Then you can use list indices to access the individual elements.
The built-in map() function in python 3 returns an iterator. Once you consume an iterator or it is exhausted, it won't yield you result any more.
a = map(lambda x: x**2, [1,2,3])
for i in a: print(a)
The result:
1
4
9
Now try,
a.__next__()
It will return you a StopIteration error, as the iterator is already exhausted.
To use index you can use list as suggested in the previous answer.

How to make sets of iterators

I want to iterate over a certain range and create several sets that contain only the current i. (In the code I don't want to do this for every i, but it's about the general principle).
for i in range(5):
s=set(i)
print(s)
It says int object is not iterable. Why doesn't this work? Please keep the answers simple, I'm a newbie.
set() takes a sequence of values to add, and a single integer is not a sequence.
You could wrap it in a tuple or a list:
s = set((i,))
s = set([i])
but the better option is to use the {..} set literal notation:
s = {i}
The notation looks a lot like creating a dictionary, but you only list values, not keys.
Demo (on Python 2, where the representation uses set([..]) notation):
>>> i = 42
>>> set((i,))
set([42])
>>> set([i])
set([42])
>>> {i}
set([42])
Python 3 reflects sets using the literal notation:
>>> i = 42
>>> {i}
{42}
Set constructor set(x) requires x to be some container, like a list, or other set. You pass an integer, python tries to iterate over it, and fails.
In order to do so you need to pass a singleton of x, like that:
for i in range(5):
s = set([i]) # or s = set((i,))
print(s)
or through simplified set constructor
for i in range(5):
s = {i}
print(s)
or construct an empty set and add your element
for i in range(5):
s = set()
s.add(i)
print(s)
instead of using a for loop in range, you can also feed it to set (or a frozenset if you dont need to change it's content):
>>> set(range(5))
# {0, 1, 2, 3, 4}

python max function using 'key' and lambda expression

I come from OOP background and trying to learn python.
I am using the max function which uses a lambda expression to return the instance of type Player having maximum totalScore among the list players.
def winner():
w = max(players, key=lambda p: p.totalScore)
The function correctly returns instance of type Player having maximum totalScore.
I am confused about the following three things:
How does the max function work? What are the arguments it is taking? I looked at the documentation but failed to understand.
What is use of the keyword key in max function? I know it is also used in context of sort function
Meaning of the lambda expression? How to read them? How do they work?
These are all very noobish conceptual questions but will help me understand the language. It would help if you could give examples to explain.
Thanks
lambda is an anonymous function, it is equivalent to:
def func(p):
return p.totalScore
Now max becomes:
max(players, key=func)
But as def statements are compound statements they can't be used where an expression is required, that's why sometimes lambda's are used.
Note that lambda is equivalent to what you'd put in a return statement of a def. Thus, you can't use statements inside a lambda, only expressions are allowed.
What does max do?
max(a, b, c, ...[, key=func]) -> value
With a single iterable argument, return its largest item. With two or
more arguments, return the largest argument.
So, it simply returns the object that is the largest.
How does key work?
By default in Python 2 key compares items based on a set of rules based on the type of the objects (for example a string is always greater than an integer).
To modify the object before comparison, or to compare based on a particular attribute/index, you've to use the key argument.
Example 1:
A simple example, suppose you have a list of numbers in string form, but you want to compare those items by their integer value.
>>> lis = ['1', '100', '111', '2']
Here max compares the items using their original values (strings are compared lexicographically so you'd get '2' as output) :
>>> max(lis)
'2'
To compare the items by their integer value use key with a simple lambda:
>>> max(lis, key=lambda x:int(x)) # compare `int` version of each item
'111'
Example 2: Applying max to a list of tuples.
>>> lis = [(1,'a'), (3,'c'), (4,'e'), (-1,'z')]
By default max will compare the items by the first index. If the first index is the same then it'll compare the second index. As in my example, all items have a unique first index, so you'd get this as the answer:
>>> max(lis)
(4, 'e')
But, what if you wanted to compare each item by the value at index 1? Simple: use lambda:
>>> max(lis, key = lambda x: x[1])
(-1, 'z')
Comparing items in an iterable that contains objects of different type:
List with mixed items:
lis = ['1','100','111','2', 2, 2.57]
In Python 2 it is possible to compare items of two different types:
>>> max(lis) # works in Python 2
'2'
>>> max(lis, key=lambda x: int(x)) # compare integer version of each item
'111'
But in Python 3 you can't do that any more:
>>> lis = ['1', '100', '111', '2', 2, 2.57]
>>> max(lis)
Traceback (most recent call last):
File "<ipython-input-2-0ce0a02693e4>", line 1, in <module>
max(lis)
TypeError: unorderable types: int() > str()
But this works, as we are comparing integer version of each object:
>>> max(lis, key=lambda x: int(x)) # or simply `max(lis, key=int)`
'111'
Strongly simplified version of max:
def max(items, key=lambda x: x):
current = item[0]
for item in items:
if key(item) > key(current):
current = item
return current
Regarding lambda:
>>> ident = lambda x: x
>>> ident(3)
3
>>> ident(5)
5
>>> times_two = lambda x: 2*x
>>> times_two(2)
4
max function is used to get the maximum out of an iterable.
The iterators may be lists, tuples, dict objects, etc. Or even custom objects as in the example you provided.
max(iterable[, key=func]) -> value
max(a, b, c, ...[, key=func]) -> value
With a single iterable argument, return its largest item.
With two or more arguments, return the largest argument.
So, the key=func basically allows us to pass an optional argument key to the function on whose basis is the given iterator/arguments are sorted & the maximum is returned.
lambda is a python keyword that acts as a pseudo function. So, when you pass player object to it, it will return player.totalScore. Thus, the iterable passed over to function max will sort according to the key totalScore of the player objects given to it & will return the player who has maximum totalScore.
If no key argument is provided, the maximum is returned according to default Python orderings.
Examples -
max(1, 3, 5, 7)
>>>7
max([1, 3, 5, 7])
>>>7
people = [('Barack', 'Obama'), ('Oprah', 'Winfrey'), ('Mahatma', 'Gandhi')]
max(people, key=lambda x: x[1])
>>>('Oprah', 'Winfrey')
How does the max function work?
It looks for the "largest" item in an iterable. I'll assume that you
can look up what that is, but if not, it's something you can loop over,
i.e. a list or string.
What is use of the keyword key in max function? I know it is also used in context of sort function
Key is a lambda function that will tell max which objects in the iterable are larger than others. Say if you were sorting some object that you created yourself, and not something obvious, like integers.
Meaning of the lambda expression? How to read them? How do they work?
That's sort of a larger question. In simple terms, a lambda is a function you can pass around, and have other pieces of code use it. Take this for example:
def sum(a, b, f):
return (f(a) + f(b))
This takes two objects, a and b, and a function f.
It calls f() on each object, then adds them together. So look at this call:
>>> sum(2, 2, lambda a: a * 2)
8
sum() takes 2, and calls the lambda expression on it. So f(a) becomes 2 * 2, which becomes 4. It then does this for b, and adds the two together.
In not so simple terms, lambdas come from lambda calculus, which is the idea of a function that returns a function; a very cool math concept for expressing computation. You can read about that here, and then actually understand it here.
It's probably better to read about this a little more, as lambdas can be confusing, and it's not immediately obvious how useful they are. Check here.
According to the documentation:
max(iterable[, key]) max(arg1, arg2, *args[, key]) Return the
largest item in an iterable or the largest of two or more arguments.
If one positional argument is provided, iterable must be a non-empty
iterable (such as a non-empty string, tuple or list). The largest item
in the iterable is returned. If two or more positional arguments are
provided, the largest of the positional arguments is returned.
The optional key argument specifies a one-argument ordering function
like that used for list.sort(). The key argument, if supplied, must be
in keyword form (for example, max(a,b,c,key=func)).
What this is saying is that in your case, you are providing a list, in this case players. Then the max function will iterate over all the items in the list and compare them to each other to get a "maximum".
As you can imagine, with a complex object like a player determining its value for comparison is tricky, so you are given the key argument to determine how the max function will decide the value of each player. In this case, you are using a lambda function to say "for each p in players get p.totalscore and use that as his value for comparison".
max is built in function which takes first argument an iterable (like list or tuple)
keyword argument key has it's default value None but it accept function to evaluate, consider it as wrapper which evaluates iterable based on function
Consider this example dictionary:
d = {'aim':99, 'aid': 45, 'axe': 59, 'big': 9, 'short': 995, 'sin':12, 'sword':1, 'friend':1000, 'artwork':23}
Ex:
>>> max(d.keys())
'sword'
As you can see if you only pass the iterable without kwarg(a function to key) it is returning maximum value of key(alphabetically)
Ex.
Instead of finding max value of key alphabetically you might need to find max key by length of key:
>>>max(d.keys(), key=lambda x: len(x))
'artwork'
in this example lambda function is returning length of key which will be iterated hence while evaluating values instead of considering alphabetically it will keep track of max length of key and returns key which has max length
Ex.
>>> max(d.keys(), key=lambda x: d[x])
'friend'
in this example lambda function is returning value of corresponding dictionary key which has maximum value
Assuming that people who come to this page actually want to know what is key= inside len(), here is the simple answer:
len() counts the length of the object. If we specify len as a key function in min(), max(), it will return the smallest/largest item based on their length.
food = ['bread', 'tea', 'banana', 'kiwi', 'tomato']
print(max(food, key=len)) # banana
print(min(food, key=len)) # tea

Command Line Python Comma Separated User Input int Values

math.pow (base/exponent) requires comma separated values...working fine for pre-assigned values, but having trouble with user-submitted values (experimenting in command line). Help appreciated as I want to develop this kind of thing eventually making a basic math test.
exp = int(raw_input())
while exp:
print math.pow(int(raw_input))
The errors I'm getting are
ValueError: invalid literal for int() with base 10: '2,3' (which seems weird as this is an exponent, not log function...)
When I try:
exp = (raw_input())
while exp:
print math.pow(exp)
I get error:
pow expected 2 arguments, got 1
Even though I'm submitting 2,3 for example (with comma).
I also tried concatenating the input with .split, but got error regarding pow requiring integers, not "list."
When you enter an input with a comma, you get a tuple. You can either use
eval(raw_input())
Or just
input()
To get this from a string to a usable format. Once you have a tuple, you can use * notation to "unpack" the tuple. So instead of calling math.pow((2, 3)), where the one argument is the tuple (2, 3), you will be calling math.pow(2, 3).
>>> exp = input()
2, 3
>>> math.pow(*exp)
8.0
"2,3" is a string, passing this to a function won't make it act like two different parameters separated by ,(as you expected).
>>> def func(arg):
... print arg
...
>>> func('a, b')
a, b # arg is a variable that stores the passed string
You should convert that string into two numbers first by splitting it at comma first and then applying int() to each if it's item.
>>> import math
>>> math.pow(*map(int, '2,3'.split(',')))
8.0
First split the string at ',' using str.split:
>>> '2,3'.split(',')
['2', '3'] #str.split returns a list
Now as we need integers so apply int() to each value:
>>> map(int, '2,3'.split(',')) #apply int() to each item of the list ['2', '3']
[2, 3]
Now as pow expects two arguments so you can use * notation to unpack this list and pass
the items to math.pow.
>>> math.pow(*[2 , 3])
8.0
A even simpler way would be to use sequence unpacking:
>>> a, b = [2, 3]
>>> math.pow(a, b)
8.0
There's another tool in python library that can convert comma separated items in a string into a tuple:
>>> from ast import literal_eval
>>> literal_eval('1, 2')
(1, 2)
>>> a,b  = literal_eval('1, 2')
>>> a
1
>>> b
2

Python integers to strings

Could you say me, how to write a function, which takes as its (one an only) argument a list of numbers and returns a list of string representations of those numbers?
For example toNum([1, 2, 3, 4]) returns ["1", "2", "3", "4"].
def to_num(a):
return map(str, a)
print to_num([1, 2, 3, 4])
prints
['1', '2', '3', '4']
using list comprehension:
def stringify(input):
return [str(num) for num in input]
Adrien already gave you an elegant answer:
def stringify(input):
return [str(num) for num in input]
That works perfectly, but if you intend to only iterate through the representations (and don't need to keep the whole list in memory for any other reason), you should instead do:
(str(num) for num in the_list)
The parenthesis instead of the brackets indicate a generator expression, just as iterable as a list, but won't fully expand on creation. This may be important if your list is large.
You just have to supply the parameters in the function call
def to_num(*numbers):# with the * you can enter as many parameters as you want
return [str(x) for x in numbers]

Categories

Resources