我有两个列表:a = [1, 2, 3]
和b = [4, 5, 6]
。
我在python中使用了两个循环从b
的每个元素中减去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]
我的结果是正确的:result = [-3., -4., -5., -2., -3., -4., -1., -2., -3.]
。
但是,我想知道是否有更优雅('pythonic')的方式来做它。
答案 0 :(得分:8)
无需使用索引。您可以迭代值。
a = [1, 2, 3]
b = [4, 5, 6]
result = []
for x in a:
for y in b:
result.append(x - y)
pythonic方式将是列表理解。
a = [1, 2, 3]
b = [4, 5, 6]
result = [x - y for x in a for y in b]
请注意,您应该在实际代码中对a
,b
,x
和y
使用有意义的名称。
答案 1 :(得分:4)
Pythonic方式将使用itertools.product
,因为它返回传递给它的迭代的笛卡尔积。由于不涉及Python循环,因此与使用循环的版本相比,它会更快:
>>> from operator import sub
>>> from itertools import starmap, product
>>> list(starmap(sub, product(a, b)))
[-3, -4, -5, -2, -3, -4, -1, -2, -3]
在NumPy中,您可以使用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])
时间比较:
>>> 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
答案 2 :(得分:4)
由于您已经使用numpy
,因此它就像这样简单:
In [29]: numpy.repeat(a, len(b)) - numpy.tile(b, len(a))
Out[29]: array([-3, -4, -5, -2, -3, -4, -1, -2, -3])
每个请求在注释中,OP想要1d输出大小N ^ 2(尽管2d可能更自然),因为numpy提供了方便的函数来将N大小的数组扩展到N ^ M,即repeat
和{ {1}}:
tile
将numpy.repeat([1,0], 2)
array([1, 1, 0, 0])
numpy.tile([1,0], 2)
array([1, 0, 1, 0])
和a
重新格式化为b
的形状后,这是p
中原生元素减法的问题。