web-dev-qa-db-ja.com

要素が一意であることがわかっている場合にセットをすばやく拡張する方法

私はタイプの複数の反復を実行しています:

_masterSet=masterSet.union(setA)
_

セットが大きくなるにつれて、これらの操作の実行にかかる時間が長くなります(予想どおり)。

SetAの各要素が既にmasterSetにあるかどうかを確認するのに時間がかかると思いますか?

私の質問は、そのmasterSetにsetAの要素がまだ含まれていないことを知っていれば、これをもっと早くできるかということです。

[更新]

この質問がまだ意見を集めていることを考えると、私は以下のコメントと回答からいくつかのことを明らかにすると思った。

I knewsetAmasterSetとは異なりますが、どのように構築されたか(チェックを処理する必要はありません)繰り返し一意性チェックが必要でした。

私はこれがmasterSetとは異なることを知っているので、今度は一意性チェックを気にしないようにmasterSet.union()プロシージャを「伝える」方法があるかどうか疑問に思いましたプログラマーの主張、彼らは間違いなくディスティックでした。 Perhpasは、いくつかの異なる「.unionWithDistinctSet()」プロシージャなどを呼び出します。

応答はこれが可能ではないことを示唆していると思います(そして実際には設定操作はとにかく十分に速いはずです)が、まだ少し速いので、ユニオンの代わりにmasterSet.update(setA)を使用します。

私はそれらの線に沿って最も明確な応答を受け入れ、その時に抱えていた問題を解決し、私の人生を続けましたが、私の仮説.unionWithDistinctSet()が今までに存在できるかどうか聞いてみたいですか?

25
Stewart_R

set.updateを使用して、マスターセットを適切に更新できます。これにより、常に新しいセットを割り当てる必要がなくなるため、set.union...よりも少し速くなるはずです。

>>> s = set(range(3))
>>> s.update(range(4))
>>> s
set([0, 1, 2, 3])

もちろん、これをループで実行している場合:

masterSet = set()
for setA in iterable:
    masterSet = masterSet.union(setA)

次のようなことを行うと、パフォーマンスが向上する場合があります。

masterSet = set().union(*iterable)

最終的に、セットのメンバーシップテストはO(1)(平均的な場合))であるため、要素が既にセットに含まれているかどうかのテストは、実際には大きなパフォーマンスヒットにはなりません。

48
mgilson

要素が一意であることがわかっている場合、セットは必ずしも最適な構造ではありません。

単純なリストは、拡張するのにはるかに高速です。

masterList = list(masterSet)
masterList.extend(setA)
6
njzk2

Mgilsonが指摘しているように、updateを使用して、セットを別のセットからインプレースで更新できます。実際には少し速くなります:

def union():
    i = set(range(10000))
    j = set(range(5000, 15000))
    return i.union(j)

def update():
    i = set(range(10000))
    j = set(range(5000, 15000))
    i.update(j)
    return i

timeit.Timer(union).timeit(10000)   # 10.351907968521118
timeit.Timer(update).timeit(10000)  # 8.83384895324707
4
Daniel Roseman

確かに、__eq__(..)メソッドが非常に高価な場合、このチェックを省略することは大きな節約になります。 CPython実装では、__eq__(..)が、同じ番号にハッシュされるセット内のすべての要素で呼び出されます。 (参照: setのソースコード 。)

ただし、セットの整合性を侵害する別の方法が開かれるため、この機能が100万年も続くことはありません。これに関連するトラブルは、(通常は無視できる)パフォーマンスの向上をはるかに上回ります。これがパフォーマンスのボトルネックと判断された場合、C++拡張機能を記述し、そのSTL <set>、これは1桁以上の高速化が必要です。

0
Evgeni Sergeev