问题:
给定 n 对象的列表( n 的数量级为10 ^ 5),以最小的时空权衡非常快速地搜索给定项目。目前的,未经优化的& prototype-y解决方案花费太长时间并消耗太多RAM (优化是不过早,即)。
在对象中没有要对其进行排序的主键,但可以将其排序到某种程度,例如以下示例,其中第一列已排序。
o1 => f, g, h
o2 => f, g, i
o3 => f, j, k
o4 => k, j, m
到目前为止,该解决方案已经嵌套过滤器:
filter(test1, filter(test2, filter(test3, the_list)))
但这很慢,因为它涉及n *(n - 1)*(n - 2)次操作,其近似于O(n ^ 3)速度,并且至少有n * 2个额外的参考列表。 / p>
作为一个说明,最好是进行就地搜索。
我还没有找到用于处理此问题的标准库。这个问题的典型解决方案是什么?
答案 0 :(得分:1)
filter(test1, filter(test2, filter(test3, the_list)))
首先,这是O(n)时间,而不是O(n ^ 3)时间。时间增加不是倍增。唯一可能更糟的是,如果test3 / test2 / test1正在做一些奇怪的事情,我们应该看看那些。
如果我们建议每次测试?功能需要10毫秒,然后我们有10 * 3 * 10 ^ 5毫秒= 50分钟。如果它是n ^ 3,那么我们有(10 * 10 ^ 5)^ 3 = 3100万年。我很确定你只有一个线性时间,你只有大量的数据。
用itertools.ifilter替换过滤器,它将避免生成列表。相反,python会一次从列表中拉出一个项目,将它传递给三个测试,并且只有当它通过时才将它传递给你。它将避免内存需求,也可能更快。
除非您使用某些索引技术,否则您无法在O(n)时间内改进。但是,索引技术的适用性取决于您在test1 / test2 / test3函数中所做的事情。如果您需要帮助,请显示这些功能的示例。
正如其他人所说,数据库旨在解决这些问题。你可以加快速度,只是重新实现数据库已经为你做的很多。
答案 1 :(得分:0)
连接每个对象的属性值以生成唯一键。您可能必须将属性填充到相同的长度以保证唯一性。构造一个哈希表以返回与键匹配的对象。
答案 2 :(得分:0)
10 ^ 5并不是那么大的对象,即使在内存中也是如此。 littletable是我编写的一个小模块,作为使用Python dicts模拟查询,支点等的实验。关于littletable查询的一个好处是任何查询或连接的结果本身都是一个新的littletable表。索引保存为keys-> table对象的序列,索引键可以定义为唯一或不唯一。
我创建了一个包含3个单字母键的140K对象表,然后查询特定键。构建表本身的时间最长,索引和查询速度非常快。
from itertools import product
from littletable import Table,DataObject
objects = Table()
alphas = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
alphas += alphas.lower()
import time
print "building table", time.time()
objects.insert_many(
DataObject(k1=k1, k2=k2, k3=k3, created=time.time())
for k1,k2,k3 in product(alphas.upper(),alphas,alphas)
)
print "table complete", time.time()
print len(objects)
print "indexing table", time.time()
for k in "k1 k2 k3".split():
objects.create_index(k)
print "index complete", time.time()
print "get specific row", time.time()
matches = objects.query(k1="X", k2="k", k3="W")
for o in matches:
print o
print time.time()
打印:
building table 1309377011.63
table complete 1309377012.52
140608
indexing table 1309377012.52
index complete 1309377012.98
get specific row 1309377012.98
{'k3': 'W', 'k2': 'k', 'k1': 'X', 'created': 1309377011.9960001}
{'k3': 'W', 'k2': 'k', 'k1': 'X', 'created': 1309377012.4260001}
1309377013.0
答案 3 :(得分:0)
在我看来,一个典型的解决方案是使用数据库查询。 SQL(原始或某种ORM)或某种对象数据库可能是MongoDB吗?
答案 4 :(得分:0)
如果您的数据位于CSV文件中,您可以尝试使用sql2csv:https://sourceforge.net/projects/sql2csv/。
编辑:原谅我早发的衰老,我的意思是这个项目:https://github.com/ccoffey/sql4csv/wiki/Examples。