2014-11-04 114 views
1

我有兩個列表:a = [1, 2, 3]b = [4, 5, 6]Pythonic的方式來編寫一個循環

我已經用python中的兩個循環從a的每個元素中減去b的每個元素。

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')的方式來做到這一點。

+1

你已經提供了你的整個代碼 – 2014-11-04 13:27:47

+2

而不是讓它更「pythonic」,這是一個荒謬的想法,使這個代碼更容易閱讀。首先讓變量名稱的方式更有意義。 – 2014-11-04 13:27:56

+2

@Puciek不明白你的意思,因爲我很清楚。我不是,糾正我。 – DimKoim 2014-11-04 13:33:08

回答

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] 

請記住,你應該爲abx並實時代碼y使用有意義的名稱。

+1

好的,優雅的和pythonic,純Python解決方案的+1 – 2014-11-04 14:01:53

+0

我會用它來實現它列表理解。我認爲這是最爲Pythonic的,因爲它在適當的地方使用函數式編程。 – 2014-11-04 14:06:32

4

Pythonic的方式將使用itertools.product,因爲它返回傳遞給它的迭代的笛卡爾乘積。由於沒有Python的循環涉及這將是比較快於版本正在使用循環:

>>> 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]) 

時機比較:

>>> 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食譜做到這一點

>>> 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 
+0

我得到147ms我的'重複/瓷磚'黑客和你的數據'OP * 1000' – 2014-11-04 14:03:49

+1

@qarma我同意它是最快的一批。 +1(在我的系統上有265ms) – 2014-11-04 14:09:49

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,即repeattile

numpy.repeat([1,0], 2) 
array([1, 1, 0, 0]) 

numpy.tile([1,0], 2) 
array([1, 0, 1, 0]) 

一旦兩個ab被重新格式化的p的形狀,它的逐元素的減法的問題,在numpy的本機。

+1

這是聰明而高效的,但你應該解釋它是如何工作的。 – 2014-11-04 14:09:38

相關問題