我有两个列表来自" cursor.fetchall()"两个不同数据来源的陈述。
列表1的结构(在调用print()时):
[(23026, ), (23038, ), (23039, ), (23040, ), (23041, )]
列表2的结构,看似截断(在执行print()语句时):
[(23038, 'Foo', 'Bar', 0),
(23039, 'Foo', 'Bar', 0),
(23054, 'Foo', 'Bar', 0)]
我需要在list_1中查找每个值以查看它是否存在于list_2中。然后,反之亦然,在一个单独的任务中查看每个list_2 [0]值是否在list_1中。
我目前正在使用的示例:
# Loop Through Rows In A List
for a in list_a:
if a == None:
break
# Loop Through Rows In B List
keep_item = False
for b in list_b:
# Check If Item From A Database Is Still In B Database
if a[0] == b[0]:
keep_item = True
break
if not keep_item:
# Delete Item
print("Deleting Item " + str(a[0]))
items_deleted += 1
每个列表包含大约30,000条记录,使用此方法时目前非常慢。
有更快的方法来执行这些查找吗?我为每次迭代执行SQL INSERT或DELETE(如果重要的话)。
答案 0 :(得分:0)
首先:您已经在SQL数据库中获得了这些值。大概有适当的指数。所以让数据库完成工作。不要将所有A和全部B读入内存,而是使用连接或子选择来只读取A中具有匹配项的A元素。
但我们假设这不合适。
要快速查找多个值,通常需要使用set或dict而不是列表。
在您的情况下,您尝试在b[0]
而不是b
上查找值,因此这将是一个字典,以您当前的b[0]
为键。而不是:
lst2 = [(23038, 'Foo', 'Bar', 0),
(23039, 'Foo', 'Bar', 0),
(23054, 'Foo', 'Bar', 0)]
......你想要这个:
dct2 = {23038: ('Foo', 'Bar', 0),
23039: ('Foo', 'Bar', 0),
23054: ('Foo', 'Bar', 0)}
理想情况下,您希望首先构建dict而不是列表。如果你不能这样做,你可以在线性时间转换:
dct2 = {b[0]: b[1:] for b in lst2}
因为你似乎从数据库游标中获取这些:大多数Python数据库都有游标,它们充当行的延迟迭代器(以最有效的方式一次获取缓冲的块),所以你可以使用光标本身:
dct2 = {row[0]: row[1:] for row in cursor}
然而,你构建你的dict或set,查找需要花费恒定时间而不是线性 - 并且它们更容易编写,以便启动:
try:
b = dct2[a[0]]
except KeyError:
print("Deleting Item " + str(a[0]))
items_deleted += 1
......或:
if a[0] not in dct2:
print("Deleting Item " + str(a[0]))
items_deleted += 1
无需循环和found
标记。
对于许多情况 - 虽然我认为它不会在这里起作用 - 但你可以让事情变得更简单。如果您有两个集合,或者一个集合和一个字典,并且您只想要第一个集合与第二个集合的交集,或者使用dict的密钥,那就是:
set1 & dct2
当基于散列的结构(如set或dict)不合适时(例如,如果不能对键进行散列),您仍然可以获得对数时间 - 不如常数,但比线性的。如果您在构建列表后只能sort
列表,则可以使用bisect
进行搜索。如果你不得不继续修改搜索之间的列表,你将需要使用一个保持排序的数据结构 - 一个平衡的二叉搜索树,像b树一样宽泛的混合b树/ deque结构,如{{1 PyPI有很多选项可供选择,你甚至可以在一本关于数据结构的好书中实现自己。