关于python:将列表切片为子列表列表

Slicing a list into a list of sub-lists

本问题已经有最佳答案,请猛点这里访问。

对于任意长度的子列表,将列表切片为切片子列表部分列表的最简单和合理有效的方法是什么?

例如,如果源列表是:

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

我们的子列表长度为3,然后我们寻求:

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

同样,如果我们的子列表长度为4,则我们寻求:

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


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

其中,n是一个块的长度。

由于您没有定义当input中的元素数不能被n除尽时,新列表的最后一个元素可能发生的情况,因此我假设这并不重要:例如,如果n等于7,那么最后一个元素等于2。


itertools模块的文档包含以下配方:

1
2
3
4
5
6
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)

此函数返回所需长度的元组的迭代器:

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


真正的Python变种(python 3):

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

创建了一个列表迭代器,并将其转换为具有相同迭代器的3x元组,然后解包到zip并再次强制转换为列表。每个迭代器通过zip从中提取一个值,但是由于只有一个迭代器对象,因此对于这三个对象,内部计数器都会全局增加。


我喜欢SilentGhost的解决方案。

我的解决方案使用Python中的函数式编程:

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

给予:

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

这假设输入列表大小可以被组大小整除。如果没有,则不包括未配对的元素。