2012-04-16 8 views
31

重複要素を含むことができる "集合"を表現する標準的な方法はありますか?Pythonは重複/繰り返し要素を持つ "set"

私が理解しているように、セットは正確に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'] 

注: はい、コレクションのこの種の正しい用語がない設定します。もっと正しいものはありますか?

コースのリストは機能しますが、必要なコレクションは順序付けされていません。セットの名前を付けるメソッドが私にとってより適切であると思われることは言うまでもありません。

+0

これを行う理由を説明することで役立つかもしれません。 – jamylak

+2

重複が必要な場合は、定義によって 'set'ではありません。あなたはあなたが思っていることを実証できますか?また、適切な容器やデータタイプを提案することができますか? –

+2

はい、これは「リスト」と呼ばれます – georg

答えて

30

あなたはmultisetを探しています。

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

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

、は、PyPIにデータ構造パッケージからbagクラスを使用します。これはPython 3のみのためです。 Python 2が必要な場合、hereはPython 2.4用に書かれたbagのレシピです。

+3

collections.Counterとpypi's bagの違いは何ですか? – max

+0

python 2.7.6で私はバッグを走らせることができます、なぜですか? – Zen

+5

ここで大きな相違点があります: 'len(counter_obj)'は、ユニークな要素の数ですが、マルチセットから期待される要素の総数は与えません。しかし、あなたは組と同じように、組合や交差点のような他のすべての操作を行うことができます。 – Phani

11

要素/カウントでのdictのアプローチは私にとっては大丈夫です。おそらくもっと機能が必要になるでしょう。 collections.Counterをご覧ください。全ての他のカウンタと

  • 簡単操作ユニオン/差を複製してO(1)要素が存在し、現在のカウント検索であるかどうかをテスト(element in listlist.count(element)よりも速い)
  • counter.elements()リストのように見える

  • -2

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

    +1

    OPがマルチセットを探していて、リストをセットに変換する可能性が最も高いです重複します。 – ComputerFellow

    +0

    編集前にこの回答を投稿しました。私のアプローチは、元のリストのビューとしてだけセットを使用しています。 –

    0

    要素の「番号」にアクセスする場合はいつでも、listを使用し、list.count(element)を使用できます。

    my_list = [1, 1, 2, 3, 3, 3] 
    
    my_list.count(1) # will return 2 
    
    0

    代替Pythonマルチセット実装では、ソート済みリストのデータ構造を使用します。 PyPIにはいくつかの実装があります。 1つのオプションはadd,remove、およびcontainsのような設定方法を効率的に実装するSortedListデータ型を実装するsortedcontainersモジュールです。 sortedcontainersモジュールは、純粋なPython、高速C実装(さらに高速)、100%ユニットテストカバレッジ、および数時間のストレステストを実装しています。

    インストールは、PyPIから簡単です:

    pip install sortedcontainers 
    

    あなたは、単にopen-source repositoryからsortedlist.pyファイルをプルダウンないpip installことができます。

    from sortedcontainers import SortedList 
    survey = SortedList(['blue', 'red', 'blue', 'green']] 
    survey.add('blue') 
    print survey.count('blue') # "3" 
    survey.remove('blue') 
    

    sortedcontainersモジュールは、他の人気の実装とperformance comparisonを維持:あなたがセットと同じように

    はそれを使用してください。

    0

    は何あなたが探していることは確かmultiset(またはバッグ)、必ずしも明確な要素のコレクション(を設定し、重複が含まれていないのに対して)です。

    マルチセットの実装はhttps://github.com/mlenzen/collections-extended(Pypyのcollections extendedモジュール)です。

    マルチセットのデータ構造は、bagと呼ばれます。 bagは、collectionsモジュールのSetクラスのサブクラスであり、モジュールの多重度を追跡するための特別な辞書を備えています。

    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のための素晴らしい方法は、各要素の出現数が袋の辞書には最新保たれているので、驚くほど速く、すべての要素の多重度を返す、nlargest(リストの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}) 
    
    関連する問題