44

重複する要素を含むことができる「セット」を表す標準的な方法はありますか?

私が理解しているように、セットには正確に 1 つまたはゼロの要素があります。機能には任意の数が必要です。

私は現在、要素をキーとして、数量を値として持つ辞書を使用していますが、これは多くの理由で間違っているようです。

動機: このようなコレクションには多くの用途があると思います。たとえば、好きな色の調査は次のように表すことができます: 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']

注: はい、セットはこの種のコレクションの正しい用語ではありません。もっと正しいものはありますか?

もちろんリストは機能しますが、必要なコレクションは順不同です。セットのメソッド命名がより適切であるように思われることは言うまでもありません。

4

8 に答える 8

42

multisetを探しています。

Python の最も近いデータ型は次のcollections.Counterとおりです。

ACounterは、dictハッシュ可能なオブジェクトをカウントするためのサブクラスです。これは、要素がディクショナリ キーとして格納され、そのカウントがディクショナリ値として格納される順序付けられていないコレクションです。カウントは、ゼロまたは負のカウントを含む任意の整数値にすることができます。このCounterクラスは、他の言語のバッグまたはマルチセットに似ています。

マルチセットを実際に実装するには、bagpypi の data-structures パッケージのクラスを使用します。これは Python 3 専用であることに注意してください。Python 2 が必要な場合は、 Python 2.4用に書かれたレシピを次に示します。bag

于 2012-04-16T14:43:23.693 に答える
16

element/count を使用した dict を使用したアプローチは、私には問題ないようです。おそらく、もう少し機能が必要です。をご覧くださいcollections.Counter

  • O(1) 要素が存在するかどうかをテストし、現在のカウントを取得します ( element in listandよりも高速ですlist.count(element))
  • counter.elements()すべての重複を含むリストのように見えます
  • 簡単操作 他のカウンターとの合体・差分
于 2012-04-16T14:34:29.460 に答える
0

あなたが探しているのは、実際にはmultiset (またはbag ) であり、必ずしも異なる要素のコレクションではありません (セットには重複は含まれません)。

ここにマルチセットの実装があります: https://github.com/mlenzen/collections-extended (Pypy のコレクション拡張モジュール)。

マルチセットのデータ構造は と呼ばれbagます。Aはモジュールからのクラスbagのサブクラスであり、要素の多様性を追跡するための追加の辞書があります。Setcollections

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)

bagisの優れたメソッドnlargest(for リストと同様Counter) は、各要素の出現回数がバッグの辞書で最新に保たれているため、すべての要素の多重度を非常に高速に返します。

>>> 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}) 
于 2015-10-16T12:14:40.367 に答える
0

プレーンlistを使用list.count(element)して、要素の「数」にアクセスしたいときにいつでも使用できます。

my_list = [1, 1, 2, 3, 3, 3]

my_list.count(1) # will return 2
于 2012-04-16T14:36:15.047 に答える
-2

重複が必要な場合はリストを使用し、セットとして操作する必要がある場合はリストをセットに変換します。

于 2012-04-16T14:34:47.440 に答える