Есть ли реализация "multimap" в Python?
Я новичок в Python, и я знаком с реализациями Multimaps в другие языки. У Python есть такая структура данных, встроенная или доступная в часто используемой библиотеке?
Чтобы проиллюстрировать, что я подразумеваю под "multimap":
a = multidict()
a[1] = 'a'
a[1] = 'b'
a[2] = 'c'
print(a[1]) # prints: ['a', 'b']
print(a[2]) # prints: ['c']
Ответы
Ответ 1
Такую вещь нет в стандартной библиотеке. Вы можете использовать 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'
Ответ 2
Просто для будущих посетителей. В настоящее время существует реализация Python для Multimap. Он доступен через pypi
Ответ 3
Stephan202 имеет правильный ответ, используйте defaultdict
. Но если вы хотите что-то с интерфейсом С++ STL multimap и намного хуже, вы можете сделать это:
multimap = []
multimap.append( (3,'a') )
multimap.append( (2,'x') )
multimap.append( (3,'b') )
multimap.sort()
Теперь, когда вы повторяете multimap
, вы получите пары, как в std::multimap
. К сожалению, это означает, что ваш код цикла начнет выглядеть таким же уродливым, как С++.
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
Или подкласс 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)
Ответ 5
В настоящее время в стандартных библиотеках Python нет мульти-карты.
WebOb имеет класс MultiDict, используемый для представления значений формы HTML, и используется несколькими инфраструктурами Python Web, поэтому реализация битва проверена.
Werkzeug также имеет класс MultiDict и по той же причине.
Ответ 6
Стандартный способ записать это в Python - с dict, элементами которого являются list
или set
. Как stephan202 говорит, вы можете несколько автоматизировать это с помощью defaultdict, но вам не нужно.
Другими словами, я бы перевел ваш код на
a = dict()
a[1] = ['a', 'b']
a[2] = ['c']
print(a[1]) # prints: ['a', 'b']
print(a[2]) # prints: ['c']
Ответ 7
Вы можете взять список кортежей, а затем отсортировать их, как если бы это была мультикарта.
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')]
Это означает, что он работает как Multimap!
Обратите внимание, что, как и в случае с несколькими картами, здесь значения также сортируются в порядке возрастания, если ключи одинаковые (для того же ключа = 2, "b" стоит перед "c", хотя мы не добавляли их в этом порядке.
Если вы хотите получить их в порядке убывания, просто измените функцию sorted() следующим образом:
listAsMultimap=sorted(listAsMultimap,reverse=True)
И после того, как вы получите вывод, как это:
[(5, 'e'), (4, 'd'), (3, 'd'), (2, 'c'), (2, 'b'), (1, 'a')]
Аналогично здесь значения находятся в порядке убывания, если ключи одинаковы.
Ответ 8
Я не ясно понимаю семантику вашего примера
a[1] = 'a'
a[1] = 'b' #??
Вторая строка a[1] = 'b'
должна заменить элемент в [1].
Если да, то вам нужно использовать словарь. Если нет - вам нужно использовать словарь списков (как уже было предложено)