nameduple查找集的复杂性

时间:2016-07-07 21:21:03

标签: python dictionary set namedtuple

你好,我有一个namedtuple因为我想在同一个对象中存储一些值。

A = namedtuple("A", "key1 key2 key3")

我将这些A存储在一个包含set()

的注册表类中
class ARegistry(object):

    def __init__(self):
        self._register = set()


    def register(self, value1, value2, value3):
        self._register.add(A(key1=value1, key2=value2, key3=value3)

    def __getitem__(self, value1):
        return next((x for x in self._registry if x.key1 == value1), None)

    def get_by_key2(self, value):
        return next((x for x in self._registry if x.key2 == value), None) 


    def get_by_key3(self, value):
        return next((x for x in self._registry if x.key3 == value), None) 

通过这种方式,我可以轻松地通过key1检索那些我在大多数情况下需要的命名元组(80%),还可以在key2或key3(其他20%)上检索:

 myobj1 = a_register["foo"]  # Search on key1
 myobj2 = a_register.get_by_key2("bar")  # Search on key2
 myobj3 = a_register.get_by_key3("bar")  # Search on key3

问题:

现在我从关于集合的文档中读到,集合中的查找是复杂度O(1)。但是,如果我将namedtuple存储在上面示例中的集合中,这仍然是正确的吗?或者这样的构造是否增加了我的注册表中对象的查找时间,并且是另一种能够按时间优先按多个键查找值的方法。

1 个答案:

答案 0 :(得分:4)

如果您要查找集合中的项目,则集合中的查找仅为O(1)。您正在查看集合中的每个项目,以查看它是否与特定标准匹配 - 这是完全不同的(平均来说它将是O(N)复杂度。)

更有效的存储方法是将元组放入一个将键映射到元组的字典中。你需要3个dicts才能以这种方式存储数据(因此,如果需要考虑,这种方法会涉及更多内存)

from collections import defaultdict

class ARegistry(object):

    def __init__(self):
        self._register = [
            defaultdict(list),  # lookup based on first item in A
            defaultdict(list),  # lookup based on second item in A
            defaultdict(list),  # lookup based on third item in A
        ]

    def register(self, value1, value2, value3):
        tup = A(key1=value1, key2=value2, key3=value3)
        for v, registry in zip(tup, self._register):
            registry[v].append(tup)

    def __getitem__(self, value1):
        return next(iter(self._register[0][value1]), None)

    def get_by_key2(self, value):
        return next(iter(self._register[1][value]), None)

    def get_by_key3(self, value):
        return next(iter(self._register[2][value]), None)