根据Python中的一组索引将列表拆分为多个部分

drj*_*eep 50 python list

基于任意数量的索引将列表拆分为多个部分的最佳方法是什么?例如,给出下面的代码

indexes = [5, 12, 17]
list = range(20)
Run Code Online (Sandbox Code Playgroud)

返回这样的东西

part1 = list[:5]
part2 = list[5:12]
part3 = list[12:17]
part4 = list[17:]
Run Code Online (Sandbox Code Playgroud)

如果没有索引,则应返回整个列表.

for*_*ran 48

这是我能想到的最简单,最pythonic的解决方案:

def partition(alist, indices):
    return [alist[i:j] for i, j in zip([0]+indices, indices+[None])]
Run Code Online (Sandbox Code Playgroud)

如果输入非常大,那么迭代器解决方案应该更方便:

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)
Run Code Online (Sandbox Code Playgroud)

当然,非常非常懒惰的解决方案(如果你不介意获取数组而不是列表,但无论如何你总是可以将它们恢复为列表):

import numpy
partition = numpy.split
Run Code Online (Sandbox Code Playgroud)

  • 那-1将切断最后一项.你可以使用`None`来处理与空切片部分相同的处理(也适用于开始,尽管它没关系) (5认同)
  • @Brian哇,我只需要切掉最后一个元素!谢谢! (2认同)

kjf*_*tch 9

我也有兴趣看到更多的Pythonic方式.但这是一个糟糕的解决方案.您需要添加对空索引列表的检查.

有点像:

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
Run Code Online (Sandbox Code Playgroud)

产生

[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16], [17, 18, 19]]
Run Code Online (Sandbox Code Playgroud)

  • 对于投掷创意的2投票不太满意.特别是没有评论.我说了解决方案的粗略性. (4认同)
  • 这就是为什么我讨厌流行语"Pythonic".这就好像用Python编写的所有内容都应该以特定于Python的特定方式编写,最好由于某种原因强行压缩到一行. (3认同)
  • 如果没有解释,该网站不应允许downvoting.它根本没用. (2认同)
  • 在我看来,"pythonic"只是意味着好的,惯用的风格.它并不意味着展示每个python功能的超凝固单线解决方案.这看起来对我来说是完美的pythonic.它适当地使用切片,当范围比xrange更合适时使用范围,并直接遍历列表而不是循环索引.Python的?校验.可理解?校验.准确?校验.+1 (2认同)

Cid*_*ide 7

我的解决方案与Il-Bhima相似.

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

替代方法

如果你愿意稍微改变你输入索引的方式,从绝对索引到相对(也就是从,[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])]
Run Code Online (Sandbox Code Playgroud)


Joh*_*hin 6

>>> def burst_seq(seq, indices):
...    startpos = 0
...    for index in indices:
...       yield seq[startpos:index]
...       startpos = index
...    yield seq[startpos:]
...
>>> list(burst_seq(range(20), [5, 12, 17]))
[[0, 1, 2, 3, 4], [5, 6, 7, 8, 9, 10, 11], [12, 13, 14, 15, 16], [17, 18, 19]]
>>> list(burst_seq(range(20), []))
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]]
>>> list(burst_seq(range(0), [5, 12, 17]))
[[], [], [], []]
>>>
Run Code Online (Sandbox Code Playgroud)

Maxima mea culpa:它使用了一个for语句,它没有使用像 itertools、zip()、None 作为哨兵、列表推导式等 whizzbang 的东西......

;-)