列表切片的快速成员资格

时间:2013-08-03 21:44:35

标签: python performance

我有一个非常大的名单'data',我需要回答相当于

的查询
if (x in data[a:b]):

表示a,b和x的不同值。

是否可以预处理数据以快速进行这些查询

3 个答案:

答案 0 :(得分:4)

主意

您可以创建dict。对于每个元素存储它出现的位置的排序列表。

要回答查询:二元搜索大于或等于a的第一个元素,检查它是否存在且小于b

的伪代码

预处理:

from collections import defaultdict

byvalue = defaultdict(list)

for i, x in enumerate(data):
    byvalue[x].append(i)

查询:

def has_index_in_slice(indices, a, b):
   r = bisect.bisect_left(indices, a)

   return r < len(indices) and indices[r] < b

def check(byvalue, x, a, b):
    indices = byvalue.get(x, None)
    if not indices: return False

    return has_index_in_slice(indices, a, b)

如果我们假设O(log N)list具有O(1)“按索引获取”复杂度,则每个查询的复杂度为dict

答案 1 :(得分:1)

是的,您可以将这些切片预处理成集,从而使成员资格查找O(1)而不是O(n)

check = set(data[a:b])
if x in check:
    # do something
if y in check:
    # do something else

答案 2 :(得分:0)

将列表放在数据库中,并利用内置的索引,优化和缓存。例如,从PostgreSQL手册:

  

创建索引后,无需进一步干预:   系统会在修改表时更新索引,它会   当它认为这样做会更多时,在查询中使用索引   比顺序表扫描更有效。

但是你也可以使用sqlite来简化(以及Python标准库中的可用性)。来自Python's documentation, regarding indexing

  

Row实例用作Connection的高度优化的row_factory   对象。它试图模仿大部分功能中的元组。

     

它支持按列名和索引,迭代,   表示,相等测试和len()。

在该页面的其他地方:

  

Row提供基于索引和不区分大小写的基于名称的访问   到几乎没有内存开销的列。它可能会更好   比你自己的自定义基于字典的方法甚至基于db_row   溶液