2011-03-09 44 views
0

我需要從一維座標列表中製作2元組列表,例如 [1, 2, 1, 5] 需要變成[(1, 2), (1, 5)]。當它發生了,我已經找到這樣做的最快,最普遍的方式,在Activestate,但代碼中列出有不透明的相對Python的新手:Python:如何將'平面'序列轉換爲一系列元組?

def group3(lst, n): 
    return itertools.izip(*[itertools.islice(lst, i, None, n) for i in range(n)]) 

誰能解釋一下這個代碼是在幹什麼英語?星號在這方面做了什麼?謝謝。

+2

查看我的[回覆](http://stackoverflow.com/questions/5239856/foggy-on-asterisk-in-python/5239873#5239873)另一個關於星號 – Cameron 2011-03-09 04:42:31

+0

的問題非常有幫助,謝謝! – 2011-03-09 15:00:18

+0

我可以在Python中解釋它。 'itertools'就是爲了提高效率。將它替換爲相應的內置函數,並且它變成了'return zip(* [lst [i :: n],用於範圍(n)])',這有望更容易理解。 – cvoinescu 2012-04-19 23:28:57

回答

2

itertools.islice函數可以從任何迭代中產生一個slice。語句:

itertools.islice(lst, 0, None, 2) 

在簡化的術語意思是「返回一個迭代其中,評價時,將在起始LST與元件在0返回所有其他元素」。該0 arg爲出發點和2爲步長值(多少跳過來獲得下一個值)

這將是最好使用一個6元素列表來說明,因爲看着[(1, 2), (1, 5)]可能不清楚哪個函數產生內部元組(它們直到最終的izip才產生)。

>>> lst = [1, 2, 3, 4, 5, 6] 
>>> list(itertools.islice(lst, 0, None, 2)) 
[1, 3, 5] 
>>> list(itertools.islice(lst, 0, None, 2)) 
[2, 4, 6] 

小心使用這個發電機;第一次調用將遍歷整個序列,排除發生器:

>>> def foo(): 
...  for i in range(6): 
...   yield i + 1 
>>> 
>>> gen = foo() 
>>> list(itertools.islice(gen, 0, None, 2) 
[1, 3, 5] 
>>> list(itertools.islice(gen, 1, None, 2) 
[] 

您的函數需要產生2個序列,賠率和均值。這是列表理解的地方:

>>> [itertools.islice(lst, i, None, 2) for i in range(2)] 
[<itertools.islice object at 0x7f958a79eaf8>, <itertools.islice object at 0x7f958a79eaa0>] 

現在你有2個islice對象準備被交錯。要做到這一點,我們可以使用zip,但itertools.izip更有效,因爲它返回一個迭代:

>>> list(zip([1, 3, 5], [2, 4, 6])) 
[(1, 2), (3, 4), (5, 6)] 
>>> tmp = itertools.izip(*[itertools.islice(lst, i, None, 2) for i in range(2)]) 
>>> tmp 
<itertools.izip object at 0x7f958a7b6cf8> 
>>> list(tmp) 
[(1, 2), (3, 4), (5, 6)] 

希望幫助澄清步驟。

+0

很清楚,謝謝。 – 2011-03-09 15:01:34

1

下面是2元組的替代版本(而不是作爲一般作爲活性狀態配方):

>>> x = [1,2,3,4,5,6,7,8] 
>>> [ (x.pop(0), x.pop(0)) for item in range(len(x)/2) ] 
[(1, 2), (3, 4), (5, 6), (7, 8)] 

這通過直到有彈出前兩個數字關閉列表形成兩個元組的列表沒有更多的配對了。

相關問題