重複する要素を含めることができる「セット」を表す標準的な方法はありますか?.
私が理解しているように、セットには要素が1つまたは0つあります。機能に任意の数を持たせたい。
現在、要素をキー、数量を値として持つ辞書を使用していますが、これは多くの理由で間違っているようです。
動機:このようなコレクションには多くの用途があると思います。たとえば、お気に入りの色の調査は次のように表すことができます。survey= ['blue'、 'red'、 'blue'、 'green']
ここでは、注文は関係ありませんが、数量は関係あります。私は次のようなことをしたいです:
survey.add('blue')
# would give survey == ['blue', 'red', 'blue', 'green', 'blue']
...そして多分
survey.remove('blue')
# would give survey == ['blue', 'red', 'green']
Notes:はい、setはこの種のコレクションの正しい用語ではありません。もっと正しいものはありますか?
もちろんリストは機能しますが、必要なコレクションは順不同です。言うまでもなく、セットのメソッド命名はより適切に思えます。
multiset を探しています。
Pythonに最も近いデータ型は collections.Counter
:
Counter
は、ハッシュ可能なオブジェクトをカウントするためのdict
サブクラスです。これは、要素が辞書キーとして格納され、それらの数が辞書値として格納される、順序付けされていないコレクションです。カウントは、ゼロまたは負のカウントを含む任意の整数値にすることができます。Counter
クラスは、他の言語のバッグまたはマルチセットに似ています。
マルチセットの実際の実装では、pypiのデータ構造パッケージの bag
クラスを使用します。これはPython 3の場合のみです。Python 2が必要な場合、 ここ はbag
Python 2.4。
Element/countを使用したdictでのアプローチは私には問題ないようです。おそらく、さらにいくつかの機能が必要です。 _collections.Counter
_ をご覧ください。
element in list
_ and list.count(element)
)counter.elements()
はすべて重複するリストのように見えますあなたが探しているのは確かに multiset (またはbag)、必ずしも別個の要素のコレクションではありません(setは重複を含みません)。
ここにマルチセットの実装があります: https://github.com/mlenzen/collections-extended (Pypyの collections extended モジュール)。
マルチセットのデータ構造はbag
と呼ばれます。 bag
は、Set
モジュールのcollections
クラスのサブクラスであり、要素の多重度を追跡するための追加の辞書を備えています。
class _basebag(Set):
"""
Base class for bag and frozenbag. Is not mutable and not hashable, so there's
no reason to use this instead of either bag or frozenbag.
"""
# Basic object methods
def __init__(self, iterable=None):
"""Create a new basebag.
If iterable isn't given, is None or is empty then the bag starts empty.
Otherwise each element from iterable will be added to the bag
however many times it appears.
This runs in O(len(iterable))
"""
self._dict = dict()
self._size = 0
if iterable:
if isinstance(iterable, _basebag):
for elem, count in iterable._dict.items():
self._inc(elem, count)
else:
for value in iterable:
self._inc(value)
bag
のniceメソッドはnlargest
(リストのCounter
と同様)であり、各要素の出現回数が維持されるため、すべての要素の多重度を非常に高速に返しますバッグの辞書の-to-date:
>>> b=bag(random.choice(string.ascii_letters) for x in xrange(10))
>>> b.nlargest()
[('p', 2), ('A', 1), ('d', 1), ('m', 1), ('J', 1), ('M', 1), ('l', 1), ('n', 1), ('W', 1)]
>>> Counter(b)
Counter({'p': 2, 'A': 1, 'd': 1, 'm': 1, 'J': 1, 'M': 1, 'l': 1, 'n': 1, 'W': 1})
重複/繰り返される要素を持つPythonの「設定」
これは、セットの定義方法によって異なります。 OPにそれを仮定するかもしれません
これらの仮定が与えられた場合、オプションは2つの抽象型(a list または multiset )に減少します。 Pythonでは通常、これらの型はそれぞれlist
およびCounter
に変換されます。観察するいくつかの機微に関する詳細を参照してください。
与えられた
import random
import collections as ct
random.seed(123)
elems = [random.randint(1, 11) for _ in range(10)]
elems
# [1, 5, 2, 7, 5, 2, 1, 7, 9, 9]
コード
複製要素のリスト:
list(elems)
# [1, 5, 2, 7, 5, 2, 1, 7, 9, 9]
複製要素の「マルチセット」:
ct.Counter(elems)
# Counter({1: 2, 5: 2, 2: 2, 7: 2, 9: 2})
詳細
データ構造について
ここには混乱しやすい用語が混在しています。明確にするために、Pythonのものと比較したいくつかの基本的な数学的データ構造を次に示します。
Type |Abbr|Order|Replicates| Math* | Python | Implementation
------------|----|-----|----------|-----------|-------------|----------------
Set |Set | n | n | {2 3 1} | {2, 3, 1} | set(el)
Ordered Set |Oset| y | n | {1, 2, 3} | - | list(dict.fromkeys(el)
Multiset |Mset| n | y | [2 1 2] | - | <see `mset` below>
List |List| y | y | [1, 2, 2] | [1, 2, 2] | list(el)
この表から、各タイプの定義を推測できます。例:setは、順序を無視して複製要素を拒否するコンテナです。対照的に、listは、順序を保持し、要素の複製を許可するコンテナです。
また、表から、次のことがわかります。
マルチセットについて
collections.Counter
はマルチセットです。多くの場合それをそのように扱うことは安全ですが、Counter
は単にkey-multiplicityペアのdict(マッピング)であることに注意してください。多重度の地図です。フラット化されたマルチセットの要素の例を参照してください。
mset = [x for k, v in ct.Counter(elems).items() for x in [k]*v]
mset
# [1, 1, 5, 5, 2, 2, 7, 7, 9, 9]
順序が残っていることに注意してください。無秩序な結果が予想される場合は、驚くかもしれません。しかし、無秩序は秩序を排除するものではありません。したがって、Counter
からマルチセットを生成できますが、Pythonでの残差の順序に関する次の条件に注意してください。
まとめ
Pythonでは、マルチセットは多重度のマップ、つまりCounter
に変換できます。これは、純粋なセットのようにランダムに順序付けされていません。マルチセットでは一般に順序は問題にならないため、ほとんどの場合は問題ありません。
関連項目
collections-extended
-collections
の追加データ型のパッケージ*数学的には、( N。Wildberger に従って、中括弧を表します{}
は、セットと括弧を意味します[]
Pythonで見られるように、リストを意味します。 Pythonとは異なり、コンマ,
は、順序を意味します。
要素の「数」にアクセスしたいときはいつでも、プレーンなlist
を使用し、list.count(element)
を使用できます。
my_list = [1, 1, 2, 3, 3, 3]
my_list.count(1) # will return 2
代替Pythonマルチセット実装は、ソートされたリストのデータ構造を使用します。PyPIにはいくつかの実装があります。1つのオプションは sortedcontainers モジュールで、 SortedListadd
、remove
、contains
などのセットのようなメソッドを効率的に実装するデータ型。sortedcontainersモジュールは、純粋なPythonで実装され、Cとして高速実装(さらに高速)、100%の単体テストカバレッジ、数時間のストレステスト。
PyPIからのインストールは簡単です。
pip install sortedcontainers
できない場合pip install
次に、sortedlist.pyファイルを open-source repository からプルダウンします。
セットと同じように使用します。
from sortedcontainers import SortedList
survey = SortedList(['blue', 'red', 'blue', 'green']]
survey.add('blue')
print survey.count('blue') # "3"
survey.remove('blue')
Sortedcontainersモジュールは、他の一般的な実装と パフォーマンス比較 も維持します。