Reputation: 1044
I have two lists: a = [1, 2, 3]
and b = [4, 5, 6]
.
I have used two loops in python to subtract each element of b
from each element of a
.
import numpy as np
a = [1, 2, 3]
b = [4, 5, 6]
p = -1
result = np.zeros(len(a)*len(a))
for i in range(0,len(a)):
for j in range(0,len(a)):
p = p + 1
result[p] = a[i] - b[j]
My result is correct: result = [-3., -4., -5., -2., -3., -4., -1., -2., -3.]
.
However, I would like to know if there is more elegant('pythonic') way to do it.
Upvotes: 2
Views: 17119
Reputation: 11781
Since you are using numpy
already, it's as simple as this:
In [29]: numpy.repeat(a, len(b)) - numpy.tile(b, len(a))
Out[29]: array([-3, -4, -5, -2, -3, -4, -1, -2, -3])
Per request in comments, OP wants 1d output size N^2 (although 2d might be more natural), for that numpy provides convenient functions to extend N-sized array to N^M, namely repeat
and tile
:
numpy.repeat([1,0], 2)
array([1, 1, 0, 0])
numpy.tile([1,0], 2)
array([1, 0, 1, 0])
Once both a
and b
are reformatted to the shape of p
, it's a matter of element-wise subtraction that's native in numpy
.
Upvotes: 5
Reputation: 250931
Pythonic way will be to use itertools.product
, as it returns Cartesian product of the iterables passed to it. As no Python loop is involved it is going to be fast compared to version that are using loop:
>>> from operator import sub
>>> from itertools import starmap, product
>>> list(starmap(sub, product(a, b)))
[-3, -4, -5, -2, -3, -4, -1, -2, -3]
In NumPy you can do this using the recipes mentioned here:
>>> arr = np.dstack(np.meshgrid(a, b)).reshape(-1, 2)
>>> np.subtract(arr[:,0], arr[:,1])
array([-3, -2, -1, -4, -3, -2, -5, -4, -3])
Timing comparisons:
>>> b = [4, 5, 6]*1000
>>> a = [1, 2, 3]*1000
>>> %timeit list(starmap(sub, product(a, b)))
1 loops, best of 3: 464 ms per loop
>>> %timeit [x - y for x in a for y in b]
1 loops, best of 3: 491 ms per loop
>>> %%timeit
result = []
for x in a:
for y in b:
result.append(x - y) #attribute lookup is slow
...
1 loops, best of 3: 908 ms per loop
>>> %%timeit
result = [];append = result.append
for x in a:
for y in b:
append(x - y)
...
1 loops, best of 3: 617 ms per loop
#Numpy version will be little faster if a and b were nd arrays.
>>> %timeit arr = np.dstack(np.meshgrid(a, b)).reshape(-1, 2);np.subtract(arr[:,0], arr[:,1])
1 loops, best of 3: 573 ms per loop
Upvotes: 5
Reputation: 13222
There is no need to use an index. You can iterate over the values.
a = [1, 2, 3]
b = [4, 5, 6]
result = []
for x in a:
for y in b:
result.append(x - y)
The pythonic way would be a list comprehension.
a = [1, 2, 3]
b = [4, 5, 6]
result = [x - y for x in a for y in b]
Please bear in mind that you should use meaningful names for a
, b
, x
and y
in real code.
Upvotes: 14