Есть ли в Python многокартовая реализация? - PullRequest
59 голосов
/ 14 ноября 2009

Я новичок в Python, и я знаком с реализациями Мультикарты на других языках . Есть ли в Python такая структура данных встроенная или доступная в широко используемой библиотеке?

Чтобы проиллюстрировать, что я имею в виду под «мультикартой»:

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

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

Ответы [ 8 ]

104 голосов
/ 14 ноября 2009

Такого нет в стандартной библиотеке. Вы можете использовать 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'
9 голосов
/ 01 июня 2014

Только для будущих посетителей. В настоящее время есть реализация Python Multimap. Это доступно через pypi

4 голосов
/ 26 июля 2013

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, и вы должны его использовать.

2 голосов
/ 08 марта 2014

Или подкласс 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)
1 голос
/ 07 мая 2019

Вы можете взять список кортежей и затем отсортировать их, как если бы это была мультикарта.

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

Аналогично, здесь значения расположены в порядке убывания, если ключи одинаковы.

1 голос
/ 16 ноября 2010

Стандартный способ написать это на Python - это диктовка, каждый элемент которой равен list или set. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *.

Другими словами, я бы перевел ваш код на

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

print(a[1])  # prints: ['a', 'b']
print(a[2])  # prints: ['c']
1 голос
/ 16 ноября 2010

В стандартных библиотеках Python нет мультикарты.

В WebOb есть класс MultiDict , используемый для представления значений форм HTML, и он используется несколькими веб-фреймворками Python, поэтому реализация проверена в бою.

Werkzeug также имеет класс MultiDict , и по той же причине.

0 голосов
/ 14 ноября 2009

Я не совсем понимаю семантику вашего примера

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

Вторая строка a[1] = 'b' должна заменить элемент в [1]. Если да, то вам нужно использовать словарь. Если нет - вам нужно использовать словарь списков (как уже предлагалось)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...