Вопрос по dictionary, python – Структура данных для реализации словаря с несколькими индексами?

11

Я ищу структуру данных, которая содержит одинаковые значения в двух разных индексах, где я могу получить доступ к данным с помощьюeither one.

Пример:

x = mysticalDataStructure()
x.add(1,'karl', dog)
x.add(2,'lisa', cat)

$ x[1].age
2
$ x['karl'].age
2
$ x[1].age = 4
$ x['karl'].age
4

Есть ли что-нибудь заранее или каков мой лучший способ прокрутки (мне нужен доступ через индекс (число, идущее от 0 до n с шагом 1) и через строку).

collections.ordereddict кажется, не имеет быстрого произвольного доступа через позицию, насколько я вижу, я могу пройти его только с помощью итератора, пока не достигну элементаi (Могу вставить в правильном порядке).

@martineau: да, именно ted
Смотрите этот ответ / модуль:stackoverflow.com/questions/11449232/multiple-keys-per-value/… formiaczek
Если вы изменяете значение одним ключом, ожидаете ли вы, что новое значение будет получено другим ключом? martineau

Ваш Ответ

3   ответа
7
class MultiKeyDict(object):

    def __init__(self, **kwargs):
        self._keys = {}
        self._data = {}
        for k, v in kwargs.iteritems():
            self[k] = v

    def __getitem__(self, key):
        try:
            return self._data[key]
        except KeyError:
            return self._data[self._keys[key]]

    def __setitem__(self, key, val):
        try:
            self._data[self._keys[key]] = val
        except KeyError:
            if isinstance(key, tuple):
               if not key:
                  raise ValueError(u'Empty tuple cannot be used as a key')
               key, other_keys = key[0], key[1:]
            else:
               other_keys = []
            self._data[key] = val
            for k in other_keys:
                self._keys[k] = key

    def add_keys(self, to_key, new_keys):
        if to_key not in self._data:
            to_key = self._keys[to_key]
        for key in new_keys:
            self._keys[key] = to_key


    @classmethod
    def from_dict(cls, dic):
        result = cls()
        for key, val in dic.items():
            result[key] = val
        return result

>>> d = MultiKeyDict(a=1, b=2)
>>> d['c', 'd'] = 3 # two keys for one value
>>> print d['c'], d['d']
3 3
>>> d['c'] = 4
>>> print d['d']
4
>>> d.add_keys('d', ('e',))
>>> d['e']
4
>>> d2 = MultiKeyDict.from_dict({ ('a', 'b'): 1 })
>>> d2['a'] = 2
>>> d2['b']
2
@martineau, это всего лишь эскиз, чтобы объяснить концепцию
@martineau, учитывая завершенность, да, но мне это не понадобится в моем случае ted
идеально, это просто потрясающе, хотя мне нужно сделать два доступа к списку, я также могу хранить экземпляры неизменяемых типов. ted
@ted, я немного изменил класс - теперь изменения одного ключа отражаются на другом (значение, если то же самое)
Наверное, должен иметь__delitem__() тоже.
1

maps = [dict(), dict(), dict()]

def insert(rec):
   maps[0][rec[0]] = rec
   maps[1][rec[1]] = rec
   maps[2][rec[2]] = rec

Изменения ключевых атрибутов объекта rec требуют повторной вставки. Как и любая другая карта, когда вы меняете ключ объекта.

Карты просто отображают ключ - & gt; объект, в конце концов. Они на самом деле не хранят копии объекта (это просто не сборщик мусора). Таким образом, карта - это индекс, не более того. Если вы хотите три индекса, используйте три карты. Напишите пару функций связующего кода для управления ими.

Как упомянул Trevor, вы также можете использовать общий словарь:

index = dict()

def insert(rec):
    index[rec[0]] = rec
    index[rec[1]] = rec
    index[rec[2]] = rec

тогда вы можете получить к нему доступ либо.

Остерегайтесь ключевых столкновений, хотя!

+1 отвечает на мой плохо сформулированный пример, но вы забыли, например, что у меня также есть индексы, которые не приходят от объекта, например1 как идентификатор дляdog ted
11

по которой вы не можете просто использовать словарь:

x = {}
x[1] = x['karl'] = dog
x[2] = x['lisa'] = cat

Тогда вы можете получить к нему доступ либо.

Если вы действительно не хотите повторяться, вы делаете это:

class MysticalDataStructure(dict):
    def add(self, key1, key2, value):
        return self[key1] = self[key2] = value

x = MysticalDataStructure()
x.add(1, 'karl', dog)
x.add(2, 'lisa', cat)
@ Ханс, конечно, это будет изменено, это тот же объект - объекты передаются как ссылки в python (по значению ссылки на объект - см.stackoverflow.com/a/986145/1176601)
@ Думаю, это нужно уточнить - любой ответ, включая этот, будет работать только дляmutable types конечно (3 - неизменяемый целочисленный литерал) - если вам нужно обновить 2 неизменяемых объекта одного и того же значения одновременно, лучший способ - поместить неизменяемый объект и иметь 2 ссылки на 1 изменяемый объект
x [1] = x ['karl'] = 3, x [1] = 2 не меняет x ['karl']
не может ли x [1] изменить x ['karl']?
Это тоже хорошо, используя общий индекс.

Похожие вопросы