使用列表和字典存储临时信息

0 投票
5 回答
4362 浏览
提问于 2025-04-16 04:43

我会有很多相似的对象,它们的参数也差不多。比如,一个对象的参数可能包括:

名字、布尔值、数字和列表。

这些对象的名字必须是唯一的,也就是说,不能有两个对象的名字是一样的。而布尔值、数字和列表的值可以重复。

我想我可以把这些数据存储为一个字典的列表,像这样:

list = [
  {'name':'a', 'bool':true, 'number':123, 'list':[1, 2, 3]},
  {'name':'b', 'bool':false, 'number':143, 'list':[1, 3, 5]},
  {'name':'c', 'bool':false, 'number':123, 'list':[1, 4, 5, 18]},
]

在我创建另一个字典之前,检查这个唯一名字是否已经存在于字典列表中,最快的方法是什么?我是不是需要遍历这个列表,检查每个字典里的名字?在处理这些信息时,什么方法既快又能节省内存?假设可能会有不同的相似列表同时在不同的线程或任务中处理,而且每个列表的大小可能在100到100,000个字典之间。我应该把这些列表存储在数据库里,而不是内存中吗?

我明白,也许在项目还没做好之前,不应该过于考虑优化(存储信息和线程),所以请先回答关于唯一名字查找的问题 :)

谢谢,
Alan

5 个回答

0

如果你不想改变现有的数据结构,可以使用下面的方法。否则,可以参考poke的回答。

>>> my_list = [
...   {'name':'a', 'bool':True, 'number':123, 'list':[1, 2, 3]},
...   {'name':'b', 'bool':False, 'number':143, 'list':[1, 3, 5]},
...   {'name':'c', 'bool':False, 'number':123, 'list':[1, 4, 5, 18]},
... ]
>>> def is_present(data, name):
...     return any(name == d["name"] for d in data)
... 
>>> is_present(my_list, "a")
True
>>> is_present(my_list, "b")
True
>>> is_present(my_list, "c")
True
>>> is_present(my_list, "d")
False

当你把一个可迭代对象传给any时,如果里面有任何一个元素是True,它就会返回True。

(name == d["name"] for d in data) 这个表达式会创建一个生成器。每当有人(在这里是any)请求下一个元素时,它就会从data中获取下一个元素d,然后通过表达式name == d["name"]进行转换。因为生成器是懒惰的,也就是说,只有在请求下一个元素时才会进行转换,所以这样做会占用相对较少的内存(而且无论列表的大小如何,所占用的内存量都是一样的)。

1

一旦你开始使用字典而不是列表,检查你想要的内容的最快方法是:

if 'newkey' not in items:
    # create a new record

因为你希望能够从多个线程访问这些记录,所以我建议你保持一个锁的集合。顺便说一下,这种设计应该在一开始就考虑,因为它是应用程序设计的一部分,而不是优化的一部分。

class DictLock(dict):
    def __init__(self):
        self._lock = threading.Lock()

    def __getitem__(self, key):
        # lock to prevent two threads trying to create the same
        # entry at the same time. Then they would get different locks and
        # both think that they could access the key guarded by that lock
        with self._lock:
            if key not in self.iterkeys():
                self[key] = threading.Lock()
            return super(DictLock, self).__getitem__(key)

现在,如果你想修改你的项目,可以使用这些锁来确保安全。

locks = DictLock()

with locks['a']:
    # modify a.

或者用来插入一个新元素

with locks['z']:
    #we are now the only ones (playing by the rules) accessing the 'z' key
    items['z'] = create_new_item()
6

如果名字是每个内部数据的唯一标识符,你也可以把外部数据用字典来表示:

data = {
  'a' : { 'bool':true, 'number':123, 'list':[1, 2, 3] },
  'b' : { 'bool':false, 'number':143, 'list':[1, 3, 5] },
  'c' : { 'bool':false, 'number':123, 'list':[1, 4, 5, 18] },
}

这样你就可以很方便地检查某个键是否存在。

顺便提一下,不要把你的变量命名为 listdict,因为这样会覆盖掉 Python 内置的对象。

撰写回答