Iteration over two sequences

H

Henrik Holm

I am just starting to learn Python, mostly by going through the examples
in Dive Into Python and by playing around.

Quite frequently, I find the need to iterate over two sequences at the
same time, and I have a bit of a hard time finding a way to do this in a
"pythonic" fashion. One example is a dot product. The straight-ahead
C-like way of doing it would be:

def dotproduct(a, b):
psum = 0
for i in range(len(a)):
psum += a*b
return psum

However, the range(len(a)) term is awfully un-pythonic :)
The built-in function map() gives me a way of "transposing" the a list
and the b list, and now I can handle it with a list comprehension:

def dotproduct(a, b):
return sum([x*y for x, y in map(None, a, b)])

My concern is one of efficiency: it seems to me that I have two loops
there: first one implied with map(...) and then the for loop -- which
seems like a waste since I feel I should be able to do the
multiplication via an argument to map. So far I have come up with an
alternative via defining a separate function:

def dotproduct(a, b):
def prod(x,y): return x*y
return sum(map(prod, a, b))

I suppose I could also use a lambda here -- but is there a different,
efficient, and obvious solution that I'm overlooking?


Thanks,
Henrik
 
D

Diez B. Roggisch

zip or izip is your friend:

import itertools

a = [1,2,3]
b = ['a', 'b', 'c']

for a,b in itertools.izip(a, b):
print a, b
 
P

Paul McGuire

Henrik Holm said:
I am just starting to learn Python, mostly by going through the examples
in Dive Into Python and by playing around.

Quite frequently, I find the need to iterate over two sequences at the
same time, and I have a bit of a hard time finding a way to do this in a
"pythonic" fashion. One example is a dot product. The straight-ahead
C-like way of doing it would be:

def dotproduct(a, b):
psum = 0
for i in range(len(a)):
psum += a*b
return psum

However, the range(len(a)) term is awfully un-pythonic :)
The built-in function map() gives me a way of "transposing" the a list
and the b list, and now I can handle it with a list comprehension:

def dotproduct(a, b):
return sum([x*y for x, y in map(None, a, b)])

My concern is one of efficiency: it seems to me that I have two loops
there: first one implied with map(...) and then the for loop -- which
seems like a waste since I feel I should be able to do the
multiplication via an argument to map. So far I have come up with an
alternative via defining a separate function:

def dotproduct(a, b):
def prod(x,y): return x*y
return sum(map(prod, a, b))

I suppose I could also use a lambda here -- but is there a different,
efficient, and obvious solution that I'm overlooking?


Thanks,
Henrik

--
"On some great and glorious day the plain folks of the land will reach
in their heart's desire at last and the White House will be adorned by
a downright moron."
-H.L. Mencken (1880-1956) American Writer


zip maybe?

def dotproduct(a,b):
return sum([x*y for x,y in zip(a,b)])

-- Paul
 
R

Richard Brodie

I suppose I could also use a lambda here -- but is there a different,
efficient, and obvious solution that I'm overlooking?

Check the itertools recipes in the library documentation.
 
J

John Lenton

Quite frequently, I find the need to iterate over two sequences at
the
same time, and I have a bit of a hard time finding a way to do this in a
"pythonic" fashion. One example is a dot product. The straight-ahead
C-like way of doing it would be:

def dotproduct(a, b):
psum = 0
for i in range(len(a)):
psum += a*b
return psum


for this particular example, the most pythonic way is to do nothing at
all, or, if you must call it dotproduct,
 
I

It's me

I tried this and I got:

[(1, 'a'), (2, 'b'), (3, 'c')]

But if I change:

a=[1,2]

I got:

[(1, 'c')]

Why is that? I thought I should be getting:

[(1, 'a'),(2,'b')]

?????
 
H

Henrik Holm

John Lenton said:
def dotproduct(a, b):
psum = 0
for i in range(len(a)):
psum += a*b
return psum


for this particular example, the most pythonic way is to do nothing at
all, or, if you must call it dotproduct,


Downloading, installing, and getting to know numerical modules for
Python is mext on my list :). However, I was under the impression that
Numarray is preferred to Numeric -- is that correct? Are these two
competing packages? (Hopefully this is not flame war bait...)
 
S

Steven Bethard

Henrik said:
def dotproduct(a, b):
psum = 0
for i in range(len(a)):
psum += a*b
return psum


for this particular example, the most pythonic way is to do nothing at
all, or, if you must call it dotproduct,
from Numeric import dot as dotproduct



Downloading, installing, and getting to know numerical modules for
Python is mext on my list :). However, I was under the impression that
Numarray is preferred to Numeric -- is that correct? Are these two
competing packages? (Hopefully this is not flame war bait...)


Numarray is the replacement for Numeric. Some people are still using
Numeric for a variety of reasons, e.g. they use a package that has not
been updated to use numarray, they can't afford the performance penalty
that numarray has for small arrays, etc.

Steve
 
J

John Lenton

Downloading, installing, and getting to know numerical modules for
Python is mext on my list :). However, I was under the impression that
Numarray is preferred to Numeric -- is that correct? Are these two
competing packages? (Hopefully this is not flame war bait...)

Numeric's dot uses, if the appropriate libraries are installed,
processor-tuned code (it tries to load blas, and an attempt to load
blas will load atlas if present). Last time I checked numarray did not,
and so Numeric's dot is (or was) faster than numarray's dot by an order
of magnitude (and more, as the size of the array grew).
 
S

Scott David Daniels

Henrik said:
def dotproduct(a, b):
psum = 0
for i in range(len(a)):
psum += a*b
return psum


for this particular example, the most pythonic way is to do nothing at
all, or, if you must call it dotproduct,
from Numeric import dot as dotproduct



Downloading, installing, and getting to know numerical modules for
Python is mext on my list :). However, I was under the impression that
Numarray is preferred to Numeric -- is that correct? Are these two
competing packages? (Hopefully this is not flame war bait...)

Numarray is the future, Numeric is the "past", but in the present
Numeric is better (and more mature) at some stuff than Numarray.

Learning both is not much harder than learning one, actually (they
share a lot).

--Scott David Daniels
(e-mail address removed)
 
T

Terry Reedy

It's me said:
I tried this and I got:
[(1, 'a'), (2, 'b'), (3, 'c')]
But if I change:
a=[1,2]
I got:
[(1, 'c')]
Why is that? I thought I should be getting:
[(1, 'a'),(2,'b')]
?????

Cut and paste the actual input and output for an interactive session with a
freshly started interpreter and perhaps we can answer for sure.

Terry J. Reedy
 
D

Diez B. Roggisch

My example is somewhat flawed because it assigns a and b the values of the
iteration - so in the end, b is 'c', and only setting a to [1,2] will show
your results.

Use c and d for the variables in the for-statments, and things work as
expected.
 
D

David Isaac

Scott David Daniels said:
Numarray is the future, Numeric is the "past",

This statement is not obviously true.
See the recent discussion on the developer lists.
(Search for Numeric3.)
Alan Isaac
 
S

Scott David Daniels

David said:
This statement is not obviously true. See the recent discussion on the
developer lists. (Search for Numeric3.)
Alan Isaac

I stand corrected. Sorry to have conveyed a mis-impression that I have
held for a while. It was my understanding that the Numeric code was so
hard to maintain that our fearless leader would never let it in the
codebase. Hence, Numarray was born. A quick look through some of the
Numeric3 messages leaves me with the impression that Numeric3 will be
more of a rebirth than a small change. I have used Numeric for several
big projects (that died for commercial, rather than technical, reasons),
and have certainly appreciated it. The thrust of my comment holds,
however, "learning both is not much harder than learning one."

--Scott David Daniels
(e-mail address removed)
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top