关于字典:Python中是否有’multimap’实现?

Is there a 'multimap' implementation in Python?

我对Python不熟悉,并且熟悉其他语言中的多映射实现。python是否内置了这样的数据结构,或者在常用的库中可用?

为了说明我所说的"多重映射"的含义:

1
2
3
4
5
6
7
a = multidict()
a[1] = 'a'
a[1] = 'b'
a[2] = 'c'

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


这样的东西在标准库中是不存在的。但您可以使用defaultdict

1
2
3
4
5
6
7
8
9
>>> 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']

(您可以使用set,而不是list,在这种情况下,您可以使用.add,而不是.append。)

旁白:看看你写的这两行:

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

这似乎表明您希望表达式a[1]等于两个不同的值。这对于字典来说是不可能的,因为它们的键是唯一的,并且每个键都与一个值相关联。但是,您可以逐个提取与给定键关联的列表中的所有值。您可以使用iter,然后连续调用next。或者您可以只使用两个循环:

1
2
3
4
5
6
7
>>> 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'

只为未来的游客。目前有一个多映射的python实现。通过Pypi提供


Stephan202回答正确,使用defaultdict。但是,如果你想要的东西与界面的STL的STL和更糟糕的性能,你可以做到这一点:

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

现在,当您遍历multimap时,您将得到与std::multimap中相同的对。不幸的是,这意味着你的循环代码会变得和C++一样丑陋。

1
2
3
4
5
6
7
8
9
10
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的强大功能,您应该使用它。


dict子类:

1
2
3
4
5
6
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)


您可以获取元组列表,然后像对多映射那样对它们进行排序。

1
listAsMultimap=[]

让我们附加一些元素(元组):

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

现在排序它。

10

打印后,您将获得:

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

这意味着它作为一个多重映射工作!

请注意,和multimap一样,如果键相同,这里的值也按升序排序(对于key=2,"b"在"c"之前,尽管我们没有按此顺序追加它们。)

如果要按降序排列,只需如下更改sorted()函数:

1
listAsMultimap=sorted(listAsMultimap,reverse=True)

在你得到这样的输出之后:

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

同样,如果键相同,这里的值按降序排列。


用python编写这个命令的标准方法是使用dict,它的元素分别是listset。正如stephan202所说,您可以使用默认dict实现一些自动化,但您不必这样做。

换句话说,我会把你的代码翻译成

1
2
3
4
5
6
a = dict()
a[1] = ['a', 'b']
a[2] = ['c']

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


目前在python标准libs中没有多映射。

webob有一个用于表示HTML表单值的多维类,它被一些python web框架使用,因此实现是经过战斗测试的。

Werkzeug也有一个多层面的课程,原因也是一样的。


我不清楚你的例子的语义

1
2
a[1] = 'a'
a[1] = 'b' #??

第二行a[1] = 'b'是否应在[1]处替换元件?如果是,那么你需要使用字典。如果没有-您需要使用列表字典(如已建议的那样)