2010-02-09 38 views
22

什麼是將列表分片爲任意長度子列表的切片子列表部分的列表的最簡單和合理有效的方式是什麼?將列表切分成子列表列表

例如,如果我們的源列表爲:

input = [1, 2, 3, 4, 5, 6, 7, 8, 9, ... ] 

而且我們的子列表長度爲3,那麼我們追求:

output = [ [1, 2, 3], [4, 5, 6], [7, 8, 9], ... ] 

同樣,如果我們的子列表的長度是4,然後我們追求:

output = [ [1, 2, 3, 4], [5, 6, 7, 8], ... ] 
+2

@詹姆斯:你的加入是絕對沒有關聯的。 – SilentGhost 2010-02-09 19:13:24

+1

您可能對此問題的討論感興趣(http://stackoverflow.com/questions/2095637) – telliott99 2010-02-09 20:44:45

+0

您可以使用numpy的array_split函數,例如'np.array_split(np.array(data),20)'來分割分成20個幾乎相同大小的塊。要確保塊的大小完全相同,請使用'np.split'。 – AlexG 2016-11-20 04:34:44

回答

64
[input[i:i+n] for i in range(0, len(input), n)]  # use xrange in py2k 

其中n是塊的長度。

既然你沒有定義什麼可能發生在新列表的最後一個元素時input元素的數量不整除n,我認爲這並不重要:這個你會得到最後一個元素例如,如果n等於7,則等於2。

14

itertools模塊的文檔包含以下recipe

import itertools 

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

該函數返回所希望的長度的元組的一個迭代:

>>> list(grouper(2, [1,2,3,4,5,6,7])) 
[(1, 2), (3, 4), (5, 6), (7, None)] 
+0

雖然這與任何迭代器一起工作,但當應用於給定任務時,它看起來不像我的代碼那樣高效(至少在我的測試中)。 – SilentGhost 2010-02-09 19:12:09

+3

@SilentGhost,過早優化? – 2010-02-09 19:15:42

+1

@Mike:我請你原諒? – SilentGhost 2010-02-09 19:16:50

0

我喜歡SilentGhost的溶液。

我的解決方案使用功能編程在python:

group = lambda t, n: zip(*[t[i::n] for i in range(n)]) 
group([1, 2, 3, 4], 2) 

給出:

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

這假定輸入列表的大小是由基團尺寸整除。如果不是,則不包含未配對的元素。

+0

你的第二個例子僅限於python-2.x。在py3k中'map'不能把'None'作爲第一個參數。 – SilentGhost 2010-02-09 19:51:44

+0

@SilentGhost:你說的對,我正在刪除它。 – MKTech 2010-02-09 22:45:59

7

一個真正Python的變種(蟒蛇3):

list(zip(*(iter([1,2,3,4,5,6,7,8,9]),)*3)) 

列表迭代器創建,變成了具備3元組相同的迭代器,然後解壓到拉鍊,澆鑄再次列出。通過zip從每個迭代器中提取一個值,但由於只有一個迭代器對象,所以全部三個內部計數器全局增加。

+2

這個解決方案非常棒,但是如果我不得不考慮Python的禪宗,我會說它不是非常「pythonic」:P – AkiRoss 2015-04-02 10:25:53

+1

沒錯,它是一種非pythonic pythonic解決方案;-) – CoDEmanX 2015-04-03 20:26:56

+0

如果mod的len列表不是0! – 2018-01-18 10:59:26