在Python中根据索引将列表拆分成多个部分
如何根据一些特定的位置把一个列表分成几部分,最好的方法是什么?比如,下面这段代码
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