我有两个列表: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]
Run Code Online (Sandbox Code Playgroud)
我的结果是对的:result = [-3., -4., -5., -2., -3., -4., -1., -2., -3.].
但是,我想知道是否有更优雅('pythonic')的方式来做到这一点.
无需使用索引.您可以迭代值.
a = [1, 2, 3]
b = [4, 5, 6]
result = []
for x in a:
for y in b:
result.append(x - y)
Run Code Online (Sandbox Code Playgroud)
pythonic方式将是列表理解.
a = [1, 2, 3]
b = [4, 5, 6]
result = [x - y for x in a for y in b]
Run Code Online (Sandbox Code Playgroud)
请记住,你应该使用有意义的名称a,b,x而y在真正的代码.
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]
Run Code Online (Sandbox Code Playgroud)
在 NumPy 中,您可以使用此处提到的食谱来执行此操作:
>>> 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])
Run Code Online (Sandbox Code Playgroud)
时序比较:
>>> 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
Run Code Online (Sandbox Code Playgroud)
既然你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])
Run Code Online (Sandbox Code Playgroud)
根据评论中的请求,OP 需要 1d 输出大小 N^2(尽管 2d 可能更自然),因为 numpy 提供了方便的函数将 N 大小的数组扩展到 N^M,即repeat和tile:
numpy.repeat([1,0], 2)
array([1, 1, 0, 0])
numpy.tile([1,0], 2)
array([1, 0, 1, 0])
Run Code Online (Sandbox Code Playgroud)
一旦将a和b都重新格式化为 的形状p,那就是numpy.