2

範囲ベースの選択の補完を処理するためのpython「コア」構文があるかどうか疑問に思っていました。

と言う

 a = [0,1,2,3,4,5,6]

次に、たとえば、

 offset = 1
 step = 3
 a[offset::step] = [1,4].

したがって、私の質問は次のとおりです。

「好きにしていい?

 a[~(offset::step)] == [0,2,3,5,6]

使わずにifs?」

または、「これを処理する最もPythonicな方法は何ですか?」

補遺:

可変サイズの数千のリスト(実際には粒子の軌跡)(つまり、可変時間長の軌跡)に対してこのサブサンプリング操作を行う必要があると言います。したがって、正しいインデックス セットを事前に計算することはできません。

4

3 に答える 3

2

インデックスを生成してから、リスト内包表記を使用して、それらのインデックスに一致しないすべての値を選択する必要があります。range()インデックスをテストするための効率的な方法としてオブジェクトを使用します ( xrange()Python 2 の場合):

indices = range(offset, len(a), step)
[v for i, v in enumerate(a) if i not in indices]

Python 3 (Python 2)のrange()オブジェクトxrange()は、開始値、終了値、およびステップ値のみを保持し、inテストされた値が範囲の一部である場合、テストは単純に簡単な計算を行います。

デモ:

>>> a = [0, 1, 2, 3, 4, 5, 6]
>>> offset, step = 1, 3
>>> indices = range(offset, len(a), step)
>>> indices
range(1, 7, 3)
>>> [v for i, v in enumerate(a) if i not in indices]
[0, 2, 3, 5, 6]

はい、これにはまだifステートメントを使用する必要がありますが、テストは安価で、必要に応じてジェネレータ式に組み込むことができます。

for i in (v for i, v in enumerate(a) if i not in range(offset, len(a), step)):
于 2013-10-08T09:08:01.220 に答える
2

セットは、事前にインデックスを設定しなくても、(通常) 約 1 桁高速です。

r100 = range(100)
r2 = range(3, 40, 3)

# Find indices in r100 that aren't in r2.
# This is a set difference (or symmetric difference)
## Set methods
# Precalculated is fastest:
sr100 = set(r100)
sr2 = set(r2)
%timeit sr100 - sr2
100000 loops, best of 3: 3.84 us per loop

# Non-precalculated is still faster:
%timeit set(range(100)) ^ set(range(3,40,3))
100000 loops, best of 3: 9.76 us per loop
%timeit set(xrange(100)) ^ set(xrange(3,40,3))
100000 loops, best of 3: 8.84 us per loop

# Precalculating the original indices still helps, if you can hold it in memory:
%timeit sr100 ^ set(xrange(3,40,3))
100000 loops, best of 3: 4.87 us per loop

# This is true even including converting back to list, and sorting (if necessary):
%timeit [x for x in sr100 ^ set(xrange(3,40,3))]
100000 loops, best of 3: 9.02 us per loop
%timeit sorted(x for x in sr100 ^ set(xrange(3,40,3)))
100000 loops, best of 3: 15 us per loop


## List comprehension:

# Precalculated indices
%timeit [x for x in r100 if x not in r2]
10000 loops, best of 3: 30.5 us per loop

# Non-precalculated indices, using xrange
%timeit [x for x in xrange(100) if x not in xrange(3, 40, 3)]
10000 loops, best of 3: 65.8 us per loop

# The cost appears to be in the second xrange?
%timeit [x for x in r100 if x not in xrange(3, 40, 3)]
10000 loops, best of 3: 64.3 us per loop
%timeit [x for x in xrange(100) if x not in r2]
10000 loops, best of 3: 29.9 us per loop
# xrange is not really any faster than range here - uses less memory, but still have
# to walk through entire list
%timeit [x for x in range(100) if x not in range(3, 40, 3)]
10000 loops, best of 3: 63.5 us per loop
于 2013-10-08T13:39:08.210 に答える
0

まだ if を使用していますが、以下は、必要な答えが得られると思われる単一ステップのリスト内包表記です。

>>> offset = 1
>>> step = 3
>>> a = [0,1,2,3,4,5,6]
>>> [v for i, v in enumerate(a) if not i%step == offset]
[0, 2, 3, 5, 6]
>>>

私が知らないのは、これが mod よりも範囲構成を使用するよりも多かれ少なかれ効率的であるかどうかです。

于 2013-10-08T09:21:49.760 に答える