Доступ к словарю в виде списка

У меня есть источник данных, который лучше всего моделируется с помощью словаря (это коллекция пар ключ = значение). Для конкретной цели визуализации мне нужно предоставить интерфейс доступа к данным в виде списка (в дополнение к обычному интерфейсу словаря), что означает, что вы должны быть в состоянии сделать следующее:

data["mykey"] # returns the associated value
data[12][0] # returns the 13th key in the dictionary
data[12][1] # returns the 13th value in the dictionary

Я не могу найти подходящую реализацию фасада - если я храню индексы как ключ словаря:

data[12] = ("mykey", "myval")

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

data["mykey"] = "myval"

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

Обратите внимание, что все эти реализации предполагают, что я использую OrderedDict,

Как бы вы предоставили оба интерфейса?

Если вам интересно, это для создания PyQt QAbstractTableModel где базовый контейнер данных представляет собой словарь.

Благодарю.

4 ответа

Решение

Я должен сделать то же самое, чтобы представить данные в ListCtrl, который должен быть доступен по ключу, а не по индексу (иногда, чтобы его не нужно было искать, если я получу произвольное значение для поиска). Если у вас есть список словарей, лучшее, что я нашел, - это создать еще один словарь со ссылками на те же элементы, но доступный по ключу. Это становится моей загрузкой данных в методе:

  def SetData(self, cols, data):
    for idx, row in enumerate(data):
      item = dict((k, v.rstrip() if hasattr(v, 'rstrip') else v) for k, v in zip(cols, row))

      self.data[idx] = item

      self.byid[row[0]] = item

Итак, у меня есть список словарей, доступных в self.data, а затем другой словарь в self.byid, в котором хранятся те же элементы, но по столбцу id (в данном случае столбец 0 в моих строках). Когда мне нужно обновить, пока я получаю идентификатор, я могу позвонить self.byid[id][field] = newval, Поскольку все в Python является указателем (ссылкой), изменение значения словаря, хранящегося в self.byid, отражается в списке словарей, хранящихся в self.data. Работает как шарм.

list(data.items())[12] вернет (key, value) кортеж для 13-й пары ключ-значение в вашем OrderedDict, list(data.keys())[12] вернет 13-й ключ самостоятельно, и list(data.values())[12] вернет 13-е значение.

Это, вероятно, не очень хорошая идея для большого dicts, однако, из-за того, что список воссоздается каждый раз.

(Тем не менее, это тот же метод, используемый OrderedDict в его __repr__ метод: return '%s(%r)' % (self.__class__.__name__, list(self.items())))

Возьмите ваш dict{} и создайте еще один, в котором ключи являются указателями, а значения являются либо ключами к исходному диктату, либо кортежем / списком из исходного диктанта.

d = {"key1":"value1","key2":"value2","key3":"value3"}
d2 = {1:"key1",2:"key2",3:"key3"}

Затем:

d[d2[3]]

возвращается

'value3'

Или определяя d2 используя следующее:

d2 = {1:["key1","value1"],2:["key2","value2"],3:["key3","value3"]}

Получает доступ, который вы хотели, используя d2[3][0] и d2[3][1] для ключа и значения соответственно.

dict подкласс, который пытается получить доступ к ключам на основе индекса, но не переключается на доступ по умолчанию, может сделать эту работу. Что-то вроде:

from collections import OrderedDict

class IndexableDict(OrderedDict):
    def __getitem__(self, key):
        """Attempt to return based on index, else try key"""
        try:
            _key = self.keys()[key]
            return (_key, super(IndexableDict, self).__getitem__(_key))
        except (IndexError, TypeError):
            return super(IndexableDict, self).__getitem__(key)

d = IndexableDict(spam='eggs', messiah=False)
d['messiah'] ## False
d[1] ## ('messiah', False)
d[0] ## ('spam', 'eggs')

РЕДАКТИРОВАТЬ: Это сломается, если вы используете целые числа в качестве ключей.

Другие вопросы по тегам