3

(これはプロのベスト プラクティス/パターンの関心であり、在宅ワークの要求ではありません)

  • INPUT : 任意の順序付けられていないシーケンスまたはジェネレーター項目、関数myfilter(item)は、フィルター条件が満たされている場合に True を返します

  • OUTPUT : (filter_true, filter_false)元のシーケンス順でフィルターに従って分割された要素を含む、元の型のシーケンスのタプル。

二重フィルタリングを行わずにこれをどのように表現しますか、または二重フィルタリングを使用する必要がありますか? たぶん、フィルターとループ/ジェネレーター/リストの理解nextが答えになるでしょうか?

タイプを保持する要件を取り除くか、タプル/ジェネレーターの結果のタプルを与える要件を変更する必要がありますか?ジェネレーター入力に対してジェネレーターを簡単に返すことはできませんか? (要件は自作です)

タプルの代わりに2つのストリームを提供する、現時点での最良の候補のここでのテスト

import itertools as it
from sympy.ntheory import isprime as myfilter

mylist = xrange(1000001,1010000,2)
left,right = it.tee((myfilter(x), x) for x in mylist)
filter_true = (x for p,x in left if p)
filter_false = (x for p,x in right if not p)

print 'Hundred primes and non-primes odd  numbers'
print  '\n'.join( " Prime %i, not prime %i" %
                  (next(filter_true),next(filter_false))
                  for i in range(100))
4

4 に答える 4

5

myfilterこれは、アイテムごとに1回だけ呼び出す方法でありmylist、ジェネレーターの場合にも機能します

import itertools as it
left,right = it.tee((myfilter(x), x) for x in mylist)
filter_true = (x for p,x in left if p)
filter_false = (x for p,x in right if not p)
于 2010-09-06T10:45:01.213 に答える
2

問題がメモリではなく CPU で、myfilter が重く、元のデータセットを 2 回繰り返してフィルター処理したくないとします。ここにいくつかのシングルパスのアイデアがあります:

シンプルで用途の広いバージョン (メモリーボーラス) :

filter_true=[]
filter_false=[]
for item in  items:
    if myfilter(item):
        filter_true.append(item)
    else:
        filter_false.append(item)  

メモリに優しいバージョン: (ジェネレーターでは動作しません (list(items) で使用しない限り))

while items:
    item=items.pop()
    if myfilter(item):
        filter_true.append(item)
    else:
        filter_false.append(item)  

ジェネレーターに優しいバージョン:

while True:
    try:
        item=next(items)
        if myfilter(item):
            filter_true.append(item)
        else:
            filter_false.append(item)  
    except StopIteration:
        break
于 2010-09-06T10:45:00.447 に答える
0

簡単な方法 (ただし効率は劣ります) はtee、イテラブルを使用して両方をフィルター処理することです。

import itertools
left, right = itertools.tee( mylist )
filter_true = (x for x in left if myfilter(x))
filter_false = (x for x in right if myfilter(x))

myfilterこれは、要素ごとに繰り返し呼び出されるため、最適なソリューションよりも効率的ではありません。つまり、 で要素をテストしたことがある場合、答えは既にわかっているため、leftで再テストする必要はありません。この最適化が必要な場合、実装するのは難しくありません。手がかりrightのための実装を見てください。tee返された iterable ごとに両端キューが必要になります。これには、元のシーケンスの要素を格納する必要がありますが、まだ要求されていません。

于 2010-09-06T10:02:08.493 に答える
-1

あなたの最善の策は、2つの別々のジェネレーターを構築することだと思います:

filter_true = (x for x in mylist if myfilter(x))
filter_false = (x for x in mylist if not myfilter(x))
于 2010-09-06T09:42:06.193 に答える