substituting list comprehensions for map()

J

Jon P.

I'd like to do:

resultlist = operandlist1 + operandlist2

where for example

operandlist1=[1,2,3,4,5]
operandlist2=[5,4,3,2,1]

and resultlist will become [6,6,6,6,6]. Using map(), I
can do:

map(lambda op1,op2: op1 + op2, operandlist1, operandlist2)

Is there any reasonable way to do this via a list comprehension ?
 
J

Javier Collado

Hello,

I'll do the following:
[op1+op2 for op1,op2 in zip(operandlist1, operandlist2)]

Best regards,
Javier
 
C

Chris Rebert

I'd like to do:

resultlist = operandlist1 + operandlist2

where for example

operandlist1=[1,2,3,4,5]
operandlist2=[5,4,3,2,1]

and resultlist will become [6,6,6,6,6].  Using map(), I
can do:

map(lambda op1,op2: op1 + op2, operandlist1, operandlist2)

Is there any reasonable way to do this via a list comprehension ?

results = [x+y for x,y in zip(list1, list2)]

Cheers,
Chris
 
S

Steven D'Aprano

I'd like to do:

resultlist = operandlist1 + operandlist2

where for example

operandlist1=[1,2,3,4,5]
operandlist2=[5,4,3,2,1]

and resultlist will become [6,6,6,6,6]. Using map(), I can do:

map(lambda op1,op2: op1 + op2, operandlist1, operandlist2)


If the two lists are very large, it would be faster to use this:


from operator import add
map(add, operandlist1, operandlist2)

Is there any reasonable way to do this via a list comprehension ?

[x+y for (x, y) in zip(operandlist1, operandlist2)]

If the lists are huge, you can save some temporary memory by replacing
zip with itertools.izip.
 
P

Paul Rudin

Jon P. said:
I'd like to do:

resultlist = operandlist1 + operandlist2

where for example

operandlist1=[1,2,3,4,5]
operandlist2=[5,4,3,2,1]

and resultlist will become [6,6,6,6,6]. Using map(), I
can do:

map(lambda op1,op2: op1 + op2, operandlist1, operandlist2)

Is there any reasonable way to do this via a list comprehension ?

You can do it as a list comprehension e.g. like this:

[ x + y for x, y in zip(operandlist1, operandlist2)]

Note that there is some unnecessary list building going on here and it
may be better to use itertools.izip. (In python 3 zip returns an
iterator anyhow.)
 
B

Bruno Desthuilliers

Ben Finney a écrit :
(snip)
Yes, just about any ‘map()’ operation has a corresponding list
comprehension.

Right AFAICT, but:
(Does anyone know of a counter-example, a ‘map()’
operation that doesn't have a correspondingly simple list
comprehension?)

.... depends on your definition of "simple". There are things I'd rather
not write as a list comprehension...
 
N

Neil Crighton

Steven D'Aprano said:
operandlist1=[1,2,3,4,5]
operandlist2=[5,4,3,2,1]

and resultlist will become [6,6,6,6,6]. Using map(), I can do:

map(lambda op1,op2: op1 + op2, operandlist1, operandlist2)

If the two lists are very large, it would be faster to use this:

If the two lists are *very* large and every element in each list has the same
type, you should use NumPy arrays (http://numpy.scipy.org/).
import numpy
operandlist1 = numpy.array([1, 2, 3, 4, 5])
operandlist2 = numpy.array([5, 4, 3, 2, 1])
resultlist = operandlist1 + operandlist2
resultlist
array([6, 6, 6, 6, 6])


Neil
 
D

Diez B. Roggisch

Steven said:
I'd like to do:

resultlist = operandlist1 + operandlist2

where for example

operandlist1=[1,2,3,4,5]
operandlist2=[5,4,3,2,1]

and resultlist will become [6,6,6,6,6]. Using map(), I can do:

map(lambda op1,op2: op1 + op2, operandlist1, operandlist2)


If the two lists are very large, it would be faster to use this:


from operator import add
map(add, operandlist1, operandlist2)

Is there any reasonable way to do this via a list comprehension ?

[x+y for (x, y) in zip(operandlist1, operandlist2)]

If the lists are huge, you can save some temporary memory by replacing
zip with itertools.izip.

And even more so if one needs the results one by one - then just use a
generator-expression.

Diez
 
B

Bruno Desthuilliers

Ben Finney a écrit :
That's why I qualified it as I did. I'd be interested to know a ‘map()’
usage where there isn't a correspondingly simple list comprehension;
that is, one that couldn't be done without being significantly more
complex than the corresponding ‘map()’ usage.

I know I've seen the case, and more than once, but I'm afraid I don't
have any example to publish here - I'd need to do quite a bit of
archeology :-/
 
J

J Kenneth King

Steven D'Aprano said:
I'd like to do:

resultlist = operandlist1 + operandlist2

where for example

operandlist1=[1,2,3,4,5]
operandlist2=[5,4,3,2,1]

and resultlist will become [6,6,6,6,6]. Using map(), I can do:

map(lambda op1,op2: op1 + op2, operandlist1, operandlist2)


If the two lists are very large, it would be faster to use this:


from operator import add
map(add, operandlist1, operandlist2)

This is the best solution so far.
Is there any reasonable way to do this via a list comprehension ?

[x+y for (x, y) in zip(operandlist1, operandlist2)]

If the lists are huge, you can save some temporary memory by replacing
zip with itertools.izip.

I understand the OP was asking for it, but list comprehensions aren't
the best solution in this case... it would just be line noise.

List comprehensions are good for one-off transformations where it would
only create a one-time method for map to use.
 
K

Kee Nethery

I just noticed the tag line "a place for Python". Looked it up online (http://pyfora.org/
) and it will be interesting to see if it can fill the void that I
experience (no centralized place to post and view user submitted
sample code) in the existing Python community.

As for user community fragmentation, I would guess that someone would
be less likely to create such a site if the user community needs were
being met by the official sites. There is a place for the existing old
school interaction forums (the IRC channel, the Usenet groups and
mailing lists), but there is also a place for archived user submitted
comments.

My personal preference would be a link in each sub-paragraph in the
official documentation to a wiki page devoted to that specific aspect
of the Python language. A place were users could augment the
documentation by providing sample code and by expanding out the
documentation for those of us who don't live and breath Python in our
sleep. Real Python coders would not click on the user wiki links and
all of us newbies could communicate with each other. But until a place
like that exists, perhaps Pyfora will get us part way there.

Kee
 
D

Diez B. Roggisch

Kee said:
I just noticed the tag line "a place for Python". Looked it up online
(http://pyfora.org/ ) and it will be interesting to see if it can fill the
void that I experience (no centralized place to post and view user
submitted sample code) in the existing Python community.

ASPN cookbook?

And I don't think that a phpBB (or commercial rip-off) forum can be good at
that - the search-function of these things sucks big time, and
classification through tagging or hierarchical organization is also not
possible.
My personal preference would be a link in each sub-paragraph in the
official documentation to a wiki page devoted to that specific aspect
of the Python language. A place were users could augment the
documentation by providing sample code and by expanding out the
documentation for those of us who don't live and breath Python in our
sleep. Real Python coders would not click on the user wiki links and
all of us newbies could communicate with each other. But until a place
like that exists, perhaps Pyfora will get us part way there.

This idea has been discussed before, and unfortunately not bore any fruits
so far - one of the few places PHP is actually better than Python. So I'd
love to see it happen.

However I totally fail to see how the pyfora are any step into that
direction.

Diez
 
P

Paul Rubin

Kee Nethery said:
I just noticed the tag line "a place for Python". Looked it up online
(http://pyfora.org/ ) and it will be interesting to see if it can fill
the void that I experience (no centralized place to post and view
user submitted sample code) in the existing Python community.

Something wrong with pastebin.com or any of its lookalikes?
 
S

Steven D'Aprano

Strange to say it's a solution, when it doesn't solve the stated
problem: to replace use of ‘map()’ with a list comprehension.

In context, I wasn't giving that as a replacement for map(), but as a
replacement for map-with-a-lambda.

I disagree; a list comprehension is often clearer than use of ‘map()’
with a lambda form, and I find it to be so in this case.


You obviously don't do enough functional programming :)

Apart from an occasional brain-fart where I conflate map() with filter(),
I find them perfectly readable and sensible. The only advantages to list
comps are you can filter results with an if clause, and for simple
expressions you don't need to create a function. They're non-trivial
advantages, but for me readability isn't one of them.
 
S

Steven D'Aprano

That's an unfortunate way of expressing it; it's valid Python syntax
that doesn't do what you're describing (in this case, it will bind
‘resultlist’ to a new list that is the *concatenation* of the two
original lists).

True, but it is valid mathematical syntax if you interpret lists as
vectors. I'm sure there are languages where [1,2]+[3,4] will return
[4,6]. Possibly R or Mathematica?

Yes, just about any ‘map()’ operation has a corresponding list
comprehension. (Does anyone know of a counter-example, a ‘map()’
operation that doesn't have a correspondingly simple list
comprehension?)

Everyone forgets the multiple argument form of map.

map(func, s1, s2, s3, ...)

would need to be written as:

[func(t) for f in itertools.izip_longest(s1, s2, s3, ...)]

which I guess is relatively simple, but only because izip_longest() does
the hard work.


On the other hand, list comps using an if clause can't be written as pure
maps. You can do this:

[func(x) for x in seq if cond(x)]

filter(cond, map(func, seq))


but the second version may use much more temporary memory if seq is huge
and cond very rarely true.

And I don't think you could write this as a single map:

[func(a, b) for a in seq1 for b in seq2]
 
A

Anh Hai Trinh

Yes, just about any ‘map()’ operation has a corresponding list
comprehension. (Does anyone know of a counter-example, a ‘map()’
operation that doesn't have a correspondingly simple list
comprehension?)

Try turning this into a list comprehension:

vectorsum = lambda *args: map(sum, zip(*args))

vectorsum([1,2], [3,4], [5,6])
->[9, 12]
vectorsum([1,2], [3,4], [5,6], [7,8])
->[16, 20]

Peace,

----aht
 
A

Anh Hai Trinh

On the other hand, list comps using an if clause can't be written as pure
maps. You can do this:

[func(x) for x in seq if cond(x)]

filter(cond, map(func, seq))

but the second version may use much more temporary memory if seq is huge
and cond very rarely true.

You could use ifilter, imap there to reduce memory.

And I don't think you could write this as a single map:

[func(a, b) for a in seq1 for b in seq2]

Oh you surely could:

seq1, seq2 = [1,2,3], [4,5,6]

[a+b for a in seq1 for b in seq2]
->[5, 6, 7, 6, 7, 8, 7, 8, 9]

from itertools import product
map(sum, product(seq1, seq2))
->[5, 6, 7, 6, 7, 8, 7, 8, 9]


Peace,

----aht
 
A

Anh Hai Trinh

Try turning this into a list comprehension:
  vectorsum = lambda *args: map(sum, zip(*args))

  vectorsum([1,2], [3,4], [5,6])
->[9, 12]
  vectorsum([1,2], [3,4], [5,6], [7,8])
->[16, 20]

Nvm, it's actually easy:
vectorsum = lambda *args: [sum(i) for i in zip(*args)]
 
S

Steven D'Aprano

Yes, just about any ‘map()’ operation has a corresponding list
comprehension. (Does anyone know of a counter-example, a ‘map()’
operation that doesn't have a correspondingly simple list
comprehension?)

Try turning this into a list comprehension:

vectorsum = lambda *args: map(sum, zip(*args))

vectorsum([1,2], [3,4], [5,6])
->[9, 12]
vectorsum([1,2], [3,4], [5,6], [7,8])
->[16, 20]

[sum(t) for t in zip(*args)] will do it.
args = [1,2], [3,4], [5,6]
[sum(t) for t in zip(*args)] [9, 12]
args = [1,2], [3,4], [5,6], [7,8]
[sum(t) for t in zip(*args)]
[16, 20]
 
S

Sean DiZazzo

Try turning this into a list comprehension:
  vectorsum = lambda *args: map(sum, zip(*args))

By “this” I take you to mean “the usage of ‘map’ in this code”, since
that's the limit of my question.

    >>> vectorsum = lambda *args: [sum(items) for items in zip(*args)]
    >>> vectorsum([1,2], [3,4], [5,6])
    [9, 12]
    >>> vectorsum([1,2], [3,4], [5,6], [7,8])
    [16, 20]

--
 \       “The apparent lesson of the Inquisition is that insistence on |
  `\         uniformity of belief is fatal to intellectual, moral, and |
_o__)    spiritual health.” —_The Uses Of The Past_, Herbert J. Muller |
Ben Finney

prickly
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,045
Latest member
DRCM

Latest Threads

Top