it-swarm-ja.tech

Pythonに「マルチマップ」実装はありますか?

私はPythonが初めてで、 Multimaps in otherlanguages の実装に精通しています。 Pythonには、そのようなデータ構造が組み込まれていますか、一般的に使用されるライブラリで利用できますか?

「マルチマップ」の意味を説明するために:

a = multidict()
a[1] = 'a'
a[1] = 'b'
a[2] = 'c'

print(a[1])  # prints: ['a', 'b']
print(a[2])  # prints: ['c']
58
James Bond

そのようなことは標準ライブラリにはありません。ただし、 defaultdict を使用できます。

>>> from collections import defaultdict
>>> md = defaultdict(list)
>>> md[1].append('a')
>>> md[1].append('b')
>>> md[2].append('c')
>>> md[1]
['a', 'b']
>>> md[2]
['c']

listの代わりにsetを使用できます。この場合、.addの代わりに.appendを呼び出します。)


余談として:書いた次の2行を見てください:

a[1] = 'a'
a[1] = 'b'

これは、式a[1]を2つの異なる値に等しくすることを示しているようです。辞書はキーが一意であり、それぞれが単一の値に関連付けられているため、これは不可能です。ただし、canでできることは、特定のキーに関連付けられたリスト内のすべての値を1つずつ抽出することです。 iter を使用し、その後に next を連続して呼び出すことができます。または、2つのループを使用できます。

>>> for k, v in md.items():
...     for w in v:
...         print("md[%d] = '%s'" % (k, w))
... 
md[1] = 'a'
md[1] = 'b'
md[2] = 'c'
101
Stephan202

将来の訪問者のためだけに。現在、python Multimapの実装があります。 pypi で利用可能です

9
Michal

Stephan202には正しい答えがあります。defaultdictを使用してください。しかし、C++ STL multimapのインターフェースを使用してパフォーマンスを大幅に低下させたい場合は、次のようにします。

multimap = []
multimap.append( (3,'a') )
multimap.append( (2,'x') )
multimap.append( (3,'b') )
multimap.sort()

multimapを反復処理すると、std::multimapの場合と同じようにペアを取得できます。残念ながら、それはあなたのループコードがC++のようにく見えることを意味します。

def multimap_iter(multimap,minkey,maxkey=None):
  maxkey = minkey if (maxkey is None) else maxkey
  for k,v in multimap:
    if k<minkey: continue
    if k>maxkey: break
    yield k,v

# this will print 'a','b'
for k,v in multimap_iter(multimap,3,3):
  print v

要約すると、defaultdictは本当にクールで、pythonのパワーを活用しているので、それを使用する必要があります。

4
amwinter

または、サブクラスdict

class Multimap(dict):
    def __setitem__(self, key, value):
        if key not in self:
            dict.__setitem__(self, key, [value])  # call super method to avoid recursion
        else
            self[key].append(value)
2
jay

タプルのリストを取得し、マルチマップであるかのようにソートすることができます。

listAsMultimap=[]

いくつかの要素(タプル)を追加しましょう:

listAsMultimap.append((1,'a'))
listAsMultimap.append((2,'c'))
listAsMultimap.append((3,'d'))
listAsMultimap.append((2,'b'))
listAsMultimap.append((5,'e'))
listAsMultimap.append((4,'d'))

今それをソートします。

listAsMultimap=sorted(listAsMultimap)

それを印刷した後、あなたは得るでしょう:

[(1, 'a'), (2, 'b'), (2, 'c'), (3, 'd'), (4, 'd'), (5, 'e')]

つまり、マルチマップとして機能しています!

ここでのマルチマップのように、キーが同じ場合、値も昇順でソートされます(key = 2の場合、 'b'は 'c'の前になりますが、この順序では追加しません)。

降順で取得したい場合は、sorted()関数を次のように変更してください。

listAsMultimap=sorted(listAsMultimap,reverse=True)

そして、次のような出力が得られます。

[(5, 'e'), (4, 'd'), (3, 'd'), (2, 'c'), (2, 'b'), (1, 'a')]

同様に、キーが同じ場合、値は降順です。

1
hafiz031

現在、Python標準ライブラリにはマルチマップはありません。

WebObには、HTMLフォームの値を表すために使用される MultiDict クラスがあり、いくつかのPython Webフレームワークで使用されているため、実装はテスト済みです。

Werkzeugには MultiDict クラスもあり、同じ理由で。

1
Luciano Ramalho

Python)でこれを記述する標準的な方法は、要素がそれぞれlistまたはsetである辞書を使用することです。 stephan202 says 、defaultdictでこれをいくらか自動化できますが、そうする必要はありません。

言い換えれば、私はあなたのコードを

a = dict()
a[1] = ['a', 'b']
a[2] = ['c']

print(a[1])  # prints: ['a', 'b']
print(a[2])  # prints: ['c']
1
poolie