1

かなり長くなる可能性のあるオブジェクトの Python リストがあります。flag特定の時点で、False と評価される特定の属性 (たとえば、 ) を持つリスト内のすべての要素に関心があります。そのために、次のようなリスト内包表記を使用しています。

objList = list()
# ... populate list
[x for x in objList if not x.flag]

これはうまくいくようです。サブリストを作成した後、いくつかの異なる操作を行う必要があります。

  1. サブリストに添字を付けて index の要素を取得しますind
  2. サブリストの長さを計算します (つまり、 を持つ要素の数flag == False)。
  3. 特定のオブジェクトの最初のインスタンスのサブリストを検索します (つまり、リストの.index()メソッドを使用します)。

サブリストを作成し、そのメソッドを使用して必要なデータを取得するという単純なアプローチを使用して、これらを実装しました。これらについてもっと効率的な方法があるかどうか疑問に思っています。#1 と #3 は少なくとも最適化できるように見えます。なぜなら、#1 ではind + 1サブリストの最初に一致する要素のみが必要であり、必ずしも結果セット全体ではなく、#3 では必要になるまでサブリストを検索するだけでよいからです。一致する要素を見つけます。

これを行うための良いPythonicの方法はありますか? リスト全体を作成する代わりに、何らかの方法で構文を使用し()てジェネレーターを取得できると思いますが、まだ正しい方法を見つけていません。もちろん、手動でループを作成することもできますが、理解ベースの方法と同じくらいエレガントなものを探しています。

4

3 に答える 3

2

これらの操作のいずれかを数回実行する必要がある場合は、他のメソッドのオーバーヘッドが高くなります。リストが最良の方法です。また、おそらく最も明確なので、メモリに問題がなければ、それを使用することをお勧めします。

メモリ/速度が問題になる場合は、別の方法があります。ソフトウェアの一般的なケースによっては、速度に関しては実際には遅くなる可能性があることに注意してください。

シナリオの場合:

#value = sublist[n]
value = nth(x for x in objList if not x.flag, n)

#value = len(sublist)
value = sum(not x.flag for x in objList)

#value = sublist.index(target)
value = next(dropwhile(lambda x: x != target, (x for x in objList if not x.flag)))

itertoolsドキュメントレシピを使用itertools.dropwhile()します。nth()

于 2012-10-05T18:51:30.493 に答える
1

これら 3 つのことのいずれかを行う可能性があり、複数回行う可能性があると仮定します。

その場合、基本的に必要なのは、遅延評価されるリスト クラスを作成することです。評価されたアイテムの実際の listキャッシュと残りのジェネレーターの2 つのデータを保持します。その後ll[10]、10 番目の項目ll.index('spam')まで評価し、 が見つかるまで評価し'spam'、その後len(ll)、残りのリストを評価します。その間ずっと、実際のリストに何が表示されているかをキャッシュしているので、それ以上は何も行われません。一度より。

それを構築すると、次のようになります。

LazyList(x for x in obj_list if not x.flag)

ただし、上記のように実際に使用を開始するまで、実際には何も計算されません。

于 2012-10-05T19:01:51.020 に答える
1

objList変更できるとコメントしたので、objList 自体にインデックスを付けたり検索したりする必要がない場合は、2 つの異なるリストを 1 つと 1 つだけ保存する方がよいかもしれませ.flag = True.flag = False。次に、毎回リスト内包表記で作成する代わりに、2 番目のリストを直接使用できます。

これがあなたの状況で機能する場合、おそらく最も効率的な方法です。

于 2012-10-05T19:17:10.000 に答える