Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 元组列表的快速搜索_Python_Performance_List_Sorting_Tuples - Fatal编程技术网

Python 元组列表的快速搜索

Python 元组列表的快速搜索,python,performance,list,sorting,tuples,Python,Performance,List,Sorting,Tuples,因此,我从数据库中提取了许多元组列表,格式如下: dataA=[('A','B','C',D,E,F),('A','B','C',D,E,F),…] 然后我有一个元组列表,格式如下: dataB=[('X','A','B','C',Y),('X','A','B','C',Y),…] 我需要通过匹配'A'='A','B'='B','C'='C'和其中的D>Y>E来匹配从dataA到dataB的元组。在元组匹配的地方,我将使用值'X'和'F' “A”、“B”、“C”、“X”是最多16个字符的字符串。

因此,我从数据库中提取了许多元组列表,格式如下:

dataA=[('A','B','C',D,E,F),('A','B','C',D,E,F),…]

然后我有一个元组列表,格式如下:

dataB=[('X','A','B','C',Y),('X','A','B','C',Y),…]

我需要通过匹配'A'='A','B'='B','C'='C'和其中的D>Y>E来匹配从dataA到dataB的元组。在元组匹配的地方,我将使用值'X'和'F'

“A”、“B”、“C”、“X”是最多16个字符的字符串。D、 E,F,Y是整数


我尝试了很多方法(字符串比较、嵌套for循环、设置交集),但它们都非常慢。实现这一目标的最佳方式是什么?非常感谢

这里的关键是选择正确的数据结构。tl;dr是集的区间树的dict是正确的数据结构,但这对您来说可能意义不大,并且肯定不能解释如何达到这一点

在开始之前…你能把工作推到关系数据库吗?毕竟,这些值首先是“从数据库中提取”的,而优化这些类型的查找正是RDBMS的核心所在。使用适当的索引,
从mytable中选择f,其中a=?,b=?,c=?e和d之间的
应以对数时间运行。作为奖励,您不需要获取两个表的所有行,只需要获取匹配的行


首先,您只希望元组中的前三个值完全匹配。因此,您需要一个dict,键入前三个成员,并带有匹配值:

dictA = {}
for a, b, c, *d in dataA:
    dictA.setdefault((a, b, c), set()).add(tuple(d))
这已经将每次比较的范围缩小到仅对右
a、B、C
元组进行线性搜索,而不是对所有元组进行线性搜索。这可能已经足够了


如果没有,如何减少线性搜索

如果您有一个按
D
值排序的排序列表(或二元搜索树,或其他什么),而不是
a、B、C
的一组元组,该怎么办?然后你可以找到第一个,其中
D>Y
是对数时间,而不是线性时间。但是,不幸的是,您仍然必须从那里扫描列表的其余部分,直到最后,因为它们都有
d>Y
,并且在您测试它们之前,您不知道哪些也有
Y>E
。所以你把总时间减少了50%,而不是对数

如果您有两个排序列表,一个按
D
排序,另一个按
E
排序,该怎么办?起初,这似乎很有希望,但如何将它们结合起来呢


实际上,您需要做的是将元组分解为不重叠的间隔,每个间隔包含一个或多个元组。例如,如果元组A有
D=4,E=1
,元组B有
D=6,B=3
,则区间
(1,3)
有元组
{A}
,区间
(3,4)
有元组
{A,B}
,区间
(4,6)

然后,您可以将这些不相交的间隔存储在二叉搜索树(或其他对数数据结构)中。因为它们是不相交的,所以您可以按
(begin,end,value)
字典顺序排序,或者只按
begin
排序,以您正在使用的树API更容易排序的为准


现在,搜索是对
(a,b,c)
进行散列查找,找到一个不相交的
(d,e)
间隔树,按
d
排序,然后使用
y
对该树进行对数搜索,然后检查该间隔是否
d>y>e
,答案是相应的集
{f}
在该间隔内的元组数


显然,Python中没有内置用于间隔分离的代码,但自己构建并不是那么难


事实上,PyPI上有一些库可以封装整个间隔树结构。但这不像dict,即使你不知道散列的意思,使用dict也非常容易。一旦你在头脑中牢牢记住了抽象概念,使用区间树是很容易的,但在这之前很难做到。例如,您需要仔细考虑您的开放范围(你太长了,读不下去了,代码是不是),你的代码是“代码”>D<y<E/COD>,不是Python半开式代码> D < y> P >。这里的关键是选择正确的数据结构。TL;DR是一组DIST的间隔树是正确的数据结构,但这可能对你来说意义不大,而且绝对不能解释如何到达那里。

在开始之前…你能把工作推到关系数据库吗?毕竟,这些值是“从数据库中提取的”首先,优化这些类型的查找正是RDBMS所要做的。有了适当的索引,
从mytable中选择f,其中a=?,b=?,c=?,e和d之间的
应该以对数时间运行。另外,您不需要获取两个表的所有行,只需获取匹配的行


首先,您只希望元组中的前三个值完全匹配。因此,您需要一个dict,键入前三个成员,并具有匹配的值:

dictA = {}
for a, b, c, *d in dataA:
    dictA.setdefault((a, b, c), set()).add(tuple(d))
这已经将每次比较的范围缩小到只对右
a,B,C
元组进行线性搜索,而不是对所有元组进行线性搜索。这可能已经足够了


如果没有,如何减少线性搜索

如果您有一个排序列表(或二进制搜索树,或其他什么),而不是
a、B、C
的一组元组,该怎么办,按
D
值排序?然后您可以找到第一个
D>Y
以对数时间而不是线性时间排序的值。但是,不幸的是,您仍然必须从那里一直扫描列表的其余部分,因为它们都有
D>Y
,并且在测试它们之前,您不知道哪些也有
Y
l、 所以你把总时间减少了50%,而不是对数

如果有两个排序列表,一个按for x, a, b, c, y in dataB: tree = dictA.get((a, b, c)) if tree: d, e, fs = tree.search(y) if f: for f in fs: yield x, f