Python,将索引列表转换为切片

Python,将索引列表转换为切片,python,list,slice,range,Python,List,Slice,Range,所以我有一个索引列表 [0, 1, 2, 3, 5, 7, 8, 10] 想把它转换成这个 [[0, 3], [5], [7, 8], [10]] 这将在大量索引上运行 另外,从技术上讲,这并不适用于python中的切片,我使用的工具在给定范围时比给定单个ID时更快 该模式基于范围,就像python中的切片一样。因此,在本例中,1和2被删除,因为它们已经包含在0到3的范围内。5需要单独访问,因为它不在某个范围内,等等。当大量ID包含在[0,5000]这样的范围内时,这会更有帮助。由于您希望代

所以我有一个索引列表

[0, 1, 2, 3, 5, 7, 8, 10]
想把它转换成这个

[[0, 3], [5], [7, 8], [10]]
这将在大量索引上运行

另外,从技术上讲,这并不适用于python中的切片,我使用的工具在给定范围时比给定单个ID时更快


该模式基于范围,就像python中的切片一样。因此,在本例中,1和2被删除,因为它们已经包含在0到3的范围内。5需要单独访问,因为它不在某个范围内,等等。当大量ID包含在[0,5000]这样的范围内时,这会更有帮助。

由于您希望代码速度快,我不会太花哨。直截了当的方法应该表现得相当好:

a = [0, 1, 2, 3, 5, 7, 8, 10]
it = iter(a)
start = next(it)
slices = []
for i, x in enumerate(it):
    if x - a[i] != 1:
        end = a[i]
        if start == end:
            slices.append([start])
        else:
            slices.append([start, end])
        start = x
if a[-1] == start:
    slices.append([start])
else:
    slices.append([start, a[-1]])
诚然,这看起来不太好,但我希望我能想到的更好的解决方案表现更差。(我没有做基准测试。)

下面是一个稍微好一点但速度较慢的解决方案:

from itertools import groupby
a = [0, 1, 2, 3, 5, 7, 8, 10]
slices = []
for key, it in groupby(enumerate(a), lambda x: x[1] - x[0]):
    indices = [y for x, y in it]
    if len(indices) == 1:
        slices.append([indices[0]])
    else:
        slices.append([indices[0], indices[-1]])

由于性能是一个问题,所以使用第一个,但这里有一个有趣的一行分成两行!:D

>>> from itertools import groupby, count
>>> indices = [0, 1, 2, 3, 5, 7, 8, 10]
>>> [[next(v)] + list(v)[-1:]
     for k,v in groupby(indices, lambda x,c=count(): x-next(c))]
[[0, 3], [5], [7, 8], [10]]

下面是一个使用numpy的简单python代码:

def list_to_slices(inputlist):
      """
      Convert a flatten list to a list of slices:
      test = [0,2,3,4,5,6,12,99,100,101,102,13,14,18,19,20,25]
      list_to_slices(test)
      -> [(0, 0), (2, 6), (12, 14), (18, 20), (25, 25), (99, 102)]
      """
      inputlist.sort()
      pointers = numpy.where(numpy.diff(inputlist) > 1)[0]
      pointers = zip(numpy.r_[0, pointers+1], numpy.r_[pointers, len(inputlist)-1])
      slices = [(inputlist[i], inputlist[j]) for i, j in pointers]
      return slices

你的模式是什么,以松散的一些数字和群体的其他?如果你的任务太复杂,那么在这里为这个练习编一个较小的任务,并考虑如何将它扩展到你的问题,当你知道它是如何工作的!我认为,仅仅给你一个全面的建议对你没有帮助。这个模式是基于范围的,就像python中的切片一样。因此,在本例中,1和2被删除,因为它们已经包含在0到3的范围内。5需要单独访问,因为它不在某个范围内,等等。当大量ID包含在[0,5000]等范围内时,这会更有帮助。谢谢,效果很好。。。似乎是一个简单的问题,但让我困惑的是XDI喜欢它如何与iterable类型一起工作,在我的情况下工作得很好。。。但确实假设了一个排序序列。像集合这样的东西似乎会自动对整数排序,但我不确定这在多大程度上是可信的。@Saebin,是的,它假定一个排序序列,因为这就是您在示例中使用的序列。您可以轻松使用
seq.sorted()
进行预排序。一个
集合
根本没有排序,如果它看起来只是一个巧合,可能小数字比大数字更有可能排序。
def list_to_slices(inputlist):
      """
      Convert a flatten list to a list of slices:
      test = [0,2,3,4,5,6,12,99,100,101,102,13,14,18,19,20,25]
      list_to_slices(test)
      -> [(0, 0), (2, 6), (12, 14), (18, 20), (25, 25), (99, 102)]
      """
      inputlist.sort()
      pointers = numpy.where(numpy.diff(inputlist) > 1)[0]
      pointers = zip(numpy.r_[0, pointers+1], numpy.r_[pointers, len(inputlist)-1])
      slices = [(inputlist[i], inputlist[j]) for i, j in pointers]
      return slices