Подтвердить что ты не робот

Есть ли реализация "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']
4b9b3361

Ответ 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]. Если да, то вам нужно использовать словарь. Если нет - вам нужно использовать словарь списков (как уже было предложено)