4

だから私はインデックスのリストを持っています、

[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]などの範囲に含まれます。

4

4 に答える 4

6

あなたはコードを速くしたいので、私はあまり凝ったことをしようとはしません。単純なアプローチは非常にうまく機能するはずです。

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]])
于 2012-06-11T21:36:57.133 に答える
3
def runs(seq):
    previous = None
    start = None
    for value in itertools.chain(seq, [None]):
        if start is None:
            start = value
        if previous is not None and value != previous + 1:
            if start == previous:
                yield [previous]
            else:
                yield [start, previous]
            start = value
        previous = value
于 2012-06-11T21:45:35.670 に答える
1

パフォーマンスが問題なので、@ SvenMarnachによる最初の解決策を使用しますが、ここでは1つのライナーを2つの行に分割した楽しいものを紹介します。: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]]
于 2012-06-12T06:35:33.180 に答える
0

以下は、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
于 2017-03-16T13:35:47.223 に答える