Python中有“多图”实现吗?

时间:2009-11-13 21:14:59

标签: python dictionary

我是Python的新手,我熟悉Multimaps otherlanguages的实现。 Python是否内置了这样的数据结构,或者在常用的库中可用?

用“multimap”来说明我的意思:

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

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

8 个答案:

答案 0 :(得分:100)

标准库中没有这样的东西。您可以使用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。)


撇开:看看你写的这两行:

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

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

>>> 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'

答案 1 :(得分:9)

仅限未来的访客。目前有一个Multimap的python实现。它可以通过pypi

获得

答案 2 :(得分:4)

Stephan202有正确的答案,使用defaultdict。但是如果你想要一些具有C ++ STL多图的界面并且性能更差的东西,你可以这样做:

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的强大功能,您应该使用它。

答案 3 :(得分:2)

或子类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)

答案 4 :(得分:1)

目前Python标准库中没有多地图。

WebOb有一个用于表示HTML表单值的MultiDict类,它由一些Python Web框架使用,因此实现经过了战斗测试。

Werkzeug也有一个MultiDict类,出于同样的原因。

答案 5 :(得分:1)

在Python中编写此标准的标准方法是使用dict,其元素分别为listset。作为stephan202 says,您可以使用defaultdict在某种程度上自动执行此操作,但您不必这样做。

换句话说,我会将您的代码翻译为

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

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

答案 6 :(得分:1)

您可以获取元组列表,然后可以像对待多图一样对其进行排序。

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')]

类似地,如果键相同,则值按降序排列。

答案 7 :(得分:-3)

我不清楚你的例子的语义

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

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