2010-04-13 82 views
36

我覺得我花了很多時間在Python編寫代碼,但沒有足夠的時間來創建Python的代碼。最近我遇到了一個有趣的小問題,我想可能有一個簡單,習慣的解決方案。解釋原文,我需要收集列表中的每個連續對。例如,給定列表[1,2,3,4,5,6],我想計算[(1,2),(3,4),(5,6)]蟒「所有其他元素」成語

我想出了那個看上去像是Java的編譯時間快速解決方案。重訪問題,我能做的最好的是

l = [1,2,3,4,5,6] 
[(l[2*x],l[2*x+1]) for x in range(len(l)/2)] 

其與本案折騰出最後一個數字的副作用,就是長度不連。

有沒有辦法,我缺少一個更地道的方式,或者是這個,我會得到最好的?

+0

有關「什麼是最‘Python化’的方式來遍歷在塊列表?」 http://stackoverflow.com/questions/434287/what-is-the-most-pythonic-way-to-iterate-over-a-list-in-chunks – jfs 2010-05-21 17:51:41

回答

78

這會做多一點整齊:

>>> data = [1,2,3,4,5,6] 
>>> zip(data[0::2], data[1::2]) 
[(1, 2), (3, 4), (5, 6)] 

(但如果你不熟悉範圍的「步幅」功能,它可以說是不易閱讀)。

就像你的代碼,它丟棄,你有奇數值的最後一個值。

+3

喜歡'zip'功能。 – 2010-04-13 16:17:59

+2

在執行上述操作以處理奇數項目場景之前,您可以執行'data + = [None]'。 – badp 2010-04-13 16:22:34

+1

'some_list + = [foo]'寫成'some_list.append(foo)'。 – 2010-04-13 17:14:10

8

如何使用的range()步驟功能:

[(l[n],l[n+1]) for n in range(0,len(l),2)] 
48

的一個經常被引用的是:

zip(*[iter(l)] * 2) 
+8

awsome,但讀取像perl; - ) – 2010-04-13 16:28:53

+0

的確如此,但我認爲它也是迄今爲止提出的最有效的解決方案。我會測試,brb。 – jemfinch 2010-04-13 16:30:37

+1

是的,它比RichieHindle的解決方案快10%左右,因爲它不需要任何內存分配,只需要對輸入列表進行一次迭代。 – jemfinch 2010-04-13 16:32:55

4

試試這個

def pairs(l, n): 
    return zip(*[l[i::n] for i in range(n)]) 

所以,

pairs([1, 2, 3, 4], 2)

[(1, 2), (3, 4)] 
9

我通常從itertools文檔grouper配方複製到我的驗證碼。

def grouper(n, iterable, fillvalue=None): 
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" 
    args = [iter(iterable)] * n 
    return izip_longest(fillvalue=fillvalue, *args) 
+1

提及F手冊+1 :) – tzot 2010-04-13 22:37:29

3

如果你不想失去的元素,如果它們在列表號甚至沒有嘗試這個辦法:

>>> l = [1, 2, 3, 4, 5] 
>>> [(l[i], l[i+1] if i+1 < len(l) else None) for i in range(0, len(l), 2)] 
[(1, 2), (3, 4), (5, None)] 
4

正確的做法可能是不計算清單,而是寫一個iterator- >迭代器函數。這是更通用的 - 它適用於每一個迭代,如果你想「凍結」到列表中,你可以使用「list()」函數。

def groupElements(iterable, n): 
    # For your case, you can hardcode n=2, but I wanted the general case here. 
    # Also, you do not specify what to do if the 
    # length of the list is not divisible by 2 
    # I chose here to drop such elements 
    source = iter(iterable) 
    while True: 
     l = [] 
     for i in range(n): 
      l.append(source.next()) 
     yield tuple(l) 

我很驚訝itertools模塊還沒有一個功能 - 可能是未來的修訂。在此之前,隨意使用:)

+0

這是什麼樣的性能明智? – LondonRob 2015-08-14 06:52:00

4

toolz以上版本與itertools忽視許多函數式編程細微精心打造的圖書館。partition解決了這個(有一個選項,以墊奇長的列表中的最後一項)

>>> list(toolz.partition(2, [1,2,3,4,5,6])) 
[(1, 2), (3, 4), (5, 6)] 
相關問題