49

I often do vector addition of Python lists.

Example: I have two lists like these:

a = [0.0, 1.0, 2.0]
b = [3.0, 4.0, 5.0]

I now want to add b to a to get the result a = [3.0, 5.0, 7.0].

Usually I end up doing like this:

a[0] += b[0]
a[1] += b[1]
a[2] += b[2]

Is there some efficient, standard way to do this with less typing?

UPDATE: It can be assumed that the lists are of length 3 and contain floats.

Johan Kotlinski
  • 25,185
  • 9
  • 78
  • 101

13 Answers13

51

If you need efficient vector arithmetic, try Numpy.

>>> import numpy
>>> a=numpy.array([0,1,2])
>>> b=numpy.array([3,4,5])
>>> a+b
array([3, 5, 7])
>>> 

Or (thanks, Andrew Jaffe),

>>> a += b
>>> a
array([3, 5, 7])
>>> 
Glorfindel
  • 21,988
  • 13
  • 81
  • 109
gimel
  • 83,368
  • 10
  • 76
  • 104
50

I don't think you will find a faster solution than the 3 sums proposed in the question. The advantages of numpy are visible with larger vectors, and also if you need other operators. numpy is specially useful with matrixes, witch are trick to do with python lists.

Still, yet another way to do it :D

In [1]: a = [1,2,3]

In [2]: b = [2,3,4]

In [3]: map(sum, zip(a,b))
Out[3]: [3, 5, 7]

Edit: you can also use the izip from itertools, a generator version of zip

In [5]: from itertools import izip

In [6]: map(sum, izip(a,b))
Out[6]: [3, 5, 7]
besen
  • 32,084
  • 1
  • 21
  • 12
  • 6
    Fun fact: `map` comes with `zip` functionality included. This allows to say `map(operator.add, a, b)` – Kos Nov 05 '17 at 15:03
35

While Numeric is excellent, and list-comprehension solutions OK if you actually wanted to create a new list, I'm surprised nobody suggested the "one obvious way to do it" -- a simple for loop! Best:

for i, bi in enumerate(b): a[i] += bi

Also OK, kinda sorta:

for i in xrange(len(a)): a[i] += b[i]
Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
19

If you think Numpy is overkill, this should be really fast, because this code runs in pure C (map() and __add__() are both directly implemented in C):

a = [1.0,2.0,3.0]
b = [4.0,5.0,6.0]

c = map(float.__add__, a, b)

Or alternatively, if you don't know the types in the list:

import operator
c = map(operator.add, a, b)
Georg Schölly
  • 124,188
  • 49
  • 220
  • 267
12

How about this:

a = [x+y for x,y in zip(a,b)]
RichieHindle
  • 272,464
  • 47
  • 358
  • 399
8

Or, if you're willing to use an external library (and fixed-length arrays), use numpy, which has "+=" and related operations for in-place operations.

import numpy as np
a = np.array([0, 1, 2])
b = np.array([3, 4, 5])
a += b
Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Andrew Jaffe
  • 26,554
  • 4
  • 50
  • 59
3

[a[x] + b[x] for x in range(0,len(a))]

ismail
  • 46,010
  • 9
  • 86
  • 95
2

For the general case of having a list of lists you could do something like this:

In [2]: import numpy as np

In [3]: a = np.array([[1, 1, 1], [2, 2, 2], [3, 3, 3],[4, 5, 6]])

In [4]: [sum(a[:,i]) for i in xrange(len(a[0]))]
Out[4]: [10, 11, 12]
1

If you're after concise, try...

vectors = [[0.0, 1.0, 2.0],[3.0, 4.0, 5.0]]
[sum(col) for col in zip(*vectors)]

Though I can't speak for the performance of this.

cefn
  • 2,895
  • 19
  • 28
1
list(map(lambda x:x[0]+x[1], zip(a,b)))
  • Can you explain this solution a bit? – dethtron5000 May 01 '15 at 01:40
  • Sure :) First of all, I applied **zip function** that will return a list of tuples, e.g. if `a=[1,2,3]` and `b=[4,5,6]`, `zip(a,b)` returns `[(1,4), (2,5), (3,6)]`. After that, I applied **map** in this result, **map** function takes a function as first argument and an iterable as second argument and it applies that function to every item of this iterable. In this case, the iterable is `zip(a,b)` and the function is `lambda x: x[0]+x[1]`, it receives an item `x` as argument and it returns `x[0]+x[1]`. `map()` returns a list in python2.In python3 it returns a map object, so I used `list()` – Victor Carriço May 04 '15 at 18:23
1
a = map(lambda x, y: x + y, a, b)
Martin Tournoij
  • 26,737
  • 24
  • 105
  • 146
mwei1us
  • 11
  • 1
0

You could create a function that gets the size of the array, loops through it and creating a return array which it returns.

Ólafur Waage
  • 68,817
  • 22
  • 142
  • 198
  • Thanks, but that doesn't seem very efficient. – Johan Kotlinski May 10 '09 at 11:10
  • @kotlinski. What? Size of the array is len(array) which is not a "computation" but an attribute of the list. Looping is certainly less typing than a[0]+=b[0]... a[999]+=b[999]. Also less error-prone. Also more obvious. I'll give up a little efficiency to prevent errors from mistyping. – S.Lott May 10 '09 at 12:51
  • I think my main gripe would be creating and returning a list, which would not be necessary in this case. Otherwise, yes, it's not worse than the other idea. – Johan Kotlinski May 10 '09 at 22:10
  • I only said return an array/list is because i thought you wanted that. – Ólafur Waage May 10 '09 at 23:19
  • "to get the result a = [3.0, 5.0, 7.0]." – Ólafur Waage May 10 '09 at 23:19
0

An improvement (less memory consumption) of the comprehension list

import itertools a = [x+y for x,y in itertools.izip(a,b)]

Actually if you are not sure that a will be consume then I would even go with generator expression:

(x+y for x,y in itertools.izip(a,b))

odwl
  • 2,095
  • 2
  • 17
  • 15