あなたはすべてのイテレータを一緒にリンクするitertools.chain
を使用することができます。
from itertools import chain
from collections import Iterable
def isIter(obj):
return isinstance(obj, Iterable) and not isinstance(obj,str)
def flatten(it):
seqs = (flatten(item) if isIter(item) else (item,) for item in it)
return chain(*seqs)
def enu1(it):
return set(gen(it))
これは、すべての非シーケンスの要素のためにあなたが適切に動作するチェーンのための1つのアイテム(item,)
でタプルをしなければならないことを意味しますが、ありませんそれがパフォーマンスにどのくらいの影響を与えるかを確かめてください。
あなたはセットに変換して(他のその後isIter
)単一の関数にこれを減らすことができます。
def enu2_A(it):
seqs = (enu2_A(item) if isIter(item) else (item,) for item in it)
return set(chain(*seqs))
をしかし、再び、これはenu
へのすべての再帰呼び出しのための新しいset
オブジェクトを作成し、多分にオプションを追加変換する?
def enu2(it,return_set = True):
seqs = (enu2(item,False) if isIter(item) else (item,) for item in it)
if return_set:
return set(chain(*seqs))
else:
return chain(*seqs)
が、単一の関数にそれを組み合わせることが本当にすべてであまりスピードブーストを与えるものではありません:
import timeit
a = timeit.timeit("enu1(lis)","from __main__ import enu1,lis",number=10000)
b = timeit.timeit("enu2(lis)","from __main__ import enu2,lis",number=10000)
print(a,b)
print(a/b) #ratio, more then 1 means a took longer
出力:単一に組み合わせることにより、その3%速く
0.3400449920009123 0.32908301999850664
1.0333106582115827
私はそれがあなたが期待していたスピードアップではなかったと推測しています。あなたのコードは非常に効率的です。
EDIT:ちょうど私のenu2
のベンチマークを行なったし、あなたのenu
- あなたの方法は、より速く、私は16%程度によって提供されている1、その後、あなたがあまり良く得ることができないとして、それがあるとして、それを残しています他は、その後python2に移動しcompiler.ast.flatten
または別のCレベルequivelentを使用して:
from collections import Iterable
def flatten(lis):
for item in lis:
if isinstance(item, Iterable) and not isinstance(item, str):
for x in flatten(item):
yield x
else:
yield item
def enu(obj):
return set(flatten(obj))
lis = [['c', 'd'], 2, 2, 4, 5, 3, 1, 3, ['c']]
import timeit
a = timeit.timeit("enu(lis)","from __main__ import enu,lis",number=10000)
b = timeit.timeit("set(ast.flatten(lis))","from __main__ import lis ; from compiler import ast",number=10000)
print(a,b)
print(a/b)
出力:
0.3324121500045294 0.28561264199379366
1.1638565705076622
のようになりました.Cでの操作を実行すると、プロセスが4倍高速化されましたが、compiler
パッケージは2以降は古くなっています。6 the docsによると:
バージョン2.6で撤廃
:コンパイラパッケージは、Python 3に
を削除されているので、あなたがCの拡張機能でflatten
を書いた場合、あなたも得ることができるということは十分に可能ですより良い結果が得られますが、純粋なPythonでコードを記述したい場合は、あなたが得ることができる程度に優れています。
元の 'flatten'はジェネレータなので、それを単一の関数にまとめることで大幅なスピードアップになることはまずありません。これがプログラムの重要なボトルネックでない限り、私はおそらくこれを最適化しようとすることについて心配しないでしょう... – mgilson
あなたの関数 'eue'にはNoneが返されます –
@PadraicCunningham、ありがとうそれに気付く。私はできるだけ早くそれを修正します。 –