8

そのため、Python 2.7を使用して、次のようなインデックスを表すために使用される値のリストを最も効率的に取得するにはどうすればよいか疑問に思いました:(ただし、最大250,000以上の長さ)

indices = [2, 4, 5]

次のような大きなリストからインデックスのリストを削除します:(3,000,000以上のアイテム)

numbers = [2, 6, 12, 20, 24, 40, 42, 51]

このような結果を得るには:

[2, 6, 20, 42, 51]

私は何よりも効率的な解決策を探しています。これを行うには多くの方法があることを私は知っていますが、それは私の問題ではありません。効率はです。また、この操作は何度も実行する必要があり、リストは両方とも指数関数的に小さくなります。時間の経過とともにどれだけ小さくなるかを表す方程式はありません。

編集:

番号は、リスト内で常にソートされたままであるか、インデックスが削除された後にソートに戻る必要があります。インデックスと呼ばれるリストは、ソートすることも、ソートしないこともできます。リストにある必要はありません。

4

6 に答える 6

7

効率を上げるためにnumpyライブラリの使用を検討することをお勧めします(整数のリストを扱っている場合は、とにかく悪い考えではないかもしれません)。

>>> import numpy as np
>>> a = np.array([2, 6, 12, 20, 24, 40, 42, 51])
>>> np.delete(a, [2,4,5])
array([ 2,  6, 20, 42, 51])

np.delete: http: //docs.scipy.org/doc/numpy/reference/generated/numpy.delete.html

メインアレイをそのまま維持することも検討する価値があるかもしれませんが、マスクされたアレイを維持することもできます(ただし、速度テストは行っていません...)

于 2012-11-27T00:41:04.087 に答える
6

インデックス間でスライス全体を取得する方がリスト内包表記よりも高速である可能性があるのではないかと疑っています。

def remove_indices(numbers, indices):
    result = []
    i=0
    for j in sorted(indices):
        result += numbers[i:j]
        i = j+1
    result += numbers[i:]
    return result
于 2012-11-27T01:41:32.160 に答える
4

別のオプション:

>>> numbers = [2, 6, 12, 20, 24, 40, 42, 51]
>>> indicies = [2, 4, 5]
>>> offset = 0
>>> for i in indicies:
...     del numbers[i - offset]
...     offset += 1
...
>>> numbers
[2, 6, 20, 42, 51]

編集:

したがって、この答えに絶望的に間違っていた後、私はさまざまなアプローチのそれぞれをベンチマークしました。

ここに画像の説明を入力してください

横軸はアイテム数、縦軸は秒単位の時間です。

最速のオプションは、スライスを使用して新しいリストを作成することです(@gnibblerから):

def using_slices(numbers, indices):
    result = []
    i = 0
    for j in indices:
        result += numbers[i:j]
        i = j + 1
    result += numbers[i:]

驚いたことに、それと「セット」(@Eric)ビートnumpy.delete(@Jon Clements)

これが私が使用したスクリプトです、おそらく私は何かを逃しました。

于 2012-11-27T00:36:35.130 に答える
3

これが私の最初のアプローチです。

def remove_indices(numbers, indices):
    indices = set(indices)
    return [x for i, x in enumerate(numbers) if i not in indices]

指定した条件下でテストするためのテストモジュールを次に示します。(削除する25万の300万の要素)

import random

def create_test_set():
    numbers = range(3000000)
    indices = random.sample(range(3000000), 250000)
    return numbers, indices

def remove_indices(numbers, indices):
    indices = set(indices)
    return [x for i, x in enumerate(numbers) if i not in indices]

if __name__ == '__main__':
    import time
    numbers, indices = create_test_set()
    a = time.time()
    numbers = remove_indices(numbers, indices)
    b = time.time()
    print b - a, len(numbers)

私のラップトップでは約0.6秒かかります。複数回使用する場合は、事前にインデックスを設定することを検討してください。

(FWIW bradley.ayersソリューションは、私が待ち望んでいたよりも時間がかかりました。)

編集:これは少し速いです:(0.55秒)

def remove_indices(numbers, indices):
    return [numbers[i] for i in xrange(len(numbers)) if i not in indices]
于 2012-11-27T00:40:59.093 に答える
2

それほど効率的ではありませんが、別のアプローチ

indices = set([2, 4, 5])

result = [x for i,x in enumerate(numbers) if i not in indices]
于 2012-11-27T00:41:51.933 に答える
1

それを達成するための別の異なるアプローチ:

>>> numbers = [2, 6, 12, 20, 24, 40, 42, 51]
>>> indices = [2, 4, 5]
>>> [item for item in numbers if numbers.index(item) not in indices]
[2, 6, 20, 42, 51]
于 2016-11-21T14:21:08.970 に答える