在Python中根据索引将列表拆分成多个部分

63 投票
9 回答
75581 浏览
提问于 2025-04-15 13:14

如何根据一些特定的位置把一个列表分成几部分,最好的方法是什么?比如,下面这段代码

indexes = [5, 12, 17]
list = range(20)

应该返回像这样的结果

part1 = list[:5]
part2 = list[5:12]
part3 = list[12:17]
part4 = list[17:]

如果没有指定位置,就应该返回整个列表。

9 个回答

8

我的解决方案和Il-Bhima的很相似。

>>> def parts(list_, indices):
...     indices = [0]+indices+[len(list_)]
...     return [list_[v:indices[k+1]] for k, v in enumerate(indices[:-1])]

另一种方法

如果你愿意稍微改变一下输入索引的方式,从绝对索引改为相对索引(也就是说,从 [5, 12, 17] 改为 [5, 7, 5]),下面的方法也能给你想要的结果,而且它不会生成中间的列表。

>>> from itertools import islice
>>> def parts(list_, indices):
...     i = iter(list_)
...     return [list(islice(i, n)) for n in chain(indices, [None])]
13

我也想看看用更符合Python风格的方法来做这个。不过这个方案实在不怎么样。你需要检查一下索引列表是否为空。

可以考虑这样的做法:

indexes = [5, 12, 17]
list = range(20)

output = []
prev = 0

for index in indexes:
    output.append(list[prev:index])
    prev = index

output.append(list[indexes[-1]:])

print output

这样会产生

[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16], [17, 18, 19]]
58

这是我能想到的最简单、最符合Python风格的解决方案:

def partition(alist, indices):
    return [alist[i:j] for i, j in zip([0]+indices, indices+[None])]

如果输入的数据非常大,那么使用迭代器的方案会更方便:

from itertools import izip, chain
def partition(alist, indices):
    pairs = izip(chain([0], indices), chain(indices, [None]))
    return (alist[i:j] for i, j in pairs)

当然,还有一种非常懒惰的解决方案(如果你不介意得到数组而不是列表,不过你总是可以把它们转换回列表):

import numpy
partition = numpy.split

撰写回答