What is not working with my "map" usage?

Thomas Jollans tjol at tjol.eu
Sat Sep 22 15:12:16 EDT 2018


On 22/09/2018 20:18, Victor via Python-list wrote:
> On Saturday, September 22, 2018 at 6:22:32 AM UTC-7, Peter Otten wrote:
>> Victor via Python-list wrote:
>>
>>> Let me use a different input args and display them below.  Basically, I am
>>> hoping to add up all elements of each nested list.  So at first it should
>>> start with [1,11,111] ==> 1+11+111 = 123.  But instead, it appears to take
>>> the 1st element from each nested list to add up [1,2,3] = 6.   How should
>>> it be corrected?  Thx.
>>
>> I see three options. You can
>>
>> (1) use a list comprehension
>>
>> [add_all_elements(*sub) for sub in alist]
>>
>> (2) replace map() with itertools.starmap()
>>
>> list(itertools.starmap(add_all_elements, alist))
>>
>> (3) change your function's signature from add_all_elements(*args) to
>> add_all_elements(args), either by modifying it directly or by wrapping it
>> into another function
>>
>> list(map(lambda args: add_all_elements(*args), alist))
>>
>> (3a) My personal preference would be to change the signature and then use
>> the list comprehension
>>
>> def add_all_elements(args): ...
>> [add_all_elements(sub) for sub in alist]
> 
> Hi Peter,
> Thank you for your suggested solutions.  They all work.  But I just want to know what is wrong with my doing:
> 
> list(map(add_all_elements,*alist))
> 
> Theoretically, each list element is passed to add_all_elements.  And if my alist is [[1, 11, 111], [2, 22, 222], [3, 33, 333]], then the 1st list element  must be this [1,11,111] passed as args into add_all_elements.

Now,

   alist = [[1,11,111], [2,22,222], [3,33,333]]

so `map(add_all_alements, *alist)` is equivalent to

   map(add_all_elements,
       [1,11,111],
       [2,22,222],
       [3,33,333])

According to the docs [1], map(function, iterable, ...)

"applies function to every item of iterable, yielding the results. If 
additional iterable arguments are passed, function must take that many 
arguments and is applied to the items from all iterables in parallel."

So map takes the first item(s) of the argument(s), and applies the 
function to them, followed by the second item(s), and so on.

In other words:

def map(function, *iterables):
     for args in zip(iterables):
         yield function(*args)


[1] https://docs.python.org/3/library/functions.html#map

Come to think of it, this suggests a rather silly alternative "solution":

map(add_all_elements, *zip(*alist))

> 
> In other words, the following should have happened:
> 
>>>> add_all_elements (*[1,11,111])
> My args =  (1, 11, 111)
> 
> i = 1
> BEFORE total = 0
> AFTER total = 1
> 
> i = 11
> BEFORE total = 1
> AFTER total = 12
> 
> i = 111
> BEFORE total = 12
> AFTER total = 123
> 
> FINAL total = 123
> 
> 123
> 
> Again, thanks!
> 




More information about the Python-list mailing list