如何通过2个列表优化迭代速度以获得查找值?

时间:2018-05-20 21:28:27

标签: python python-3.x

我有两个列表来自" 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(如果重要的话)。

1 个答案:

答案 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有很多选项可供选择,你甚至可以在一本关于数据结构的好书中实现自己。