Pythonic写循环的方法

时间:2014-11-04 13:25:42

标签: python list loops

我有两个列表: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')的方式来做它。

3 个答案:

答案 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]

请注意,您应该在实际代码中对abxy使用有意义的名称。

答案 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中原生元素减法的问题。