Доступ к словарю в виде списка
У меня есть источник данных, который лучше всего моделируется с помощью словаря (это коллекция пар ключ = значение). Для конкретной цели визуализации мне нужно предоставить интерфейс доступа к данным в виде списка (в дополнение к обычному интерфейсу словаря), что означает, что вы должны быть в состоянии сделать следующее:
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-е значение.
Это, вероятно, не очень хорошая идея для большого dict
s, однако, из-за того, что список воссоздается каждый раз.
(Тем не менее, это тот же метод, используемый 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')
РЕДАКТИРОВАТЬ: Это сломается, если вы используете целые числа в качестве ключей.