访问字典作为列表

5

我有一个数据源,最好用字典来建模(它是一组键值对)。由于特定的可视化需求,我需要提供类似于列表的数据访问接口(除了常规的字典接口),这意味着你应该能够执行以下操作:

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,其中底层数据容器是一个字典。
谢谢。

在该应用程序中,字典迭代器data.iteritems()有用吗? - Craig McQueen
@Craig McQueen:是的,我确定最终实现将以某种方式使用“iteritems”来创建缓存或类似的辅助结构来访问元素。 - Escualo
4个回答

3

我需要做的是在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)排序。当我需要更新时,只要获取ID,就可以调用self.byid[id][field] = newval。因为Python中的一切都是指针(引用),所以更改存储在self.byid中的字典的值会反映在存储在self.data中的字典列表中。像魔术一样运作。


有趣 - 让我理解一下。 - Escualo

1

list(data.items())[12] 将返回您的 OrderedDict 第13个键值对的 (key, value) 元组。list(data.keys())[12] 将返回第13个键名,而 list(data.values())[12] 将返回第13个键值。

然而,这对于大型 dict 可能不是一个好主意,因为列表每次都会重新创建。

(不过,这正是 OrderedDict 在其 __repr__ 方法中使用的方法:return '%s(%r)'%(self.__class__.__name__,list(self.items()))


我认为可以通过添加某种缓存来进一步利用它,以便列表只被完全创建一次。让我进一步探索你的想法。 - Escualo
我看到你决定尝试将我的建议与phkahler的建议结合起来。效果如何? - JAB

0
一个尝试按索引访问键但在默认键访问失败时的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')

编辑:如果您使用整数作为键,这将会出错。


0

将您的dict{}创建另一个字典,其中键是索引,值可以是原始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]作为键和值,可以让您获得所需的访问权限。


我认为我会将你的方法(占用内存多)与@JAB的方法(占用处理器多)混合起来,通过缓存来取得平衡。 - Escualo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接