【问题标题】:Quickly search all elements in two lists快速搜索两个列表中的所有元素
【发布时间】:2015-02-06 14:20:26
【问题描述】:

假设我有两个大列表,包含 A 类对象的 list_of_A_objects 和包含 B 类对象的列表 _of_B_objects。

他们都有字符串成员。

我希望能够搜索两个列表中的所有元素,如果 A 对象的字符串成员是 B 对象的字符串成员的子字符串,我希望它做一些事情。

如果列表很小,我下面的内容很好,但如果列表很大,则可能需要很长时间。

有没有办法让它更快。我一直在考虑以某种方式使用字典,因为它们的查找速度很快,但我无法弄清楚。

这是我目前所拥有的。

class A:
    def __init__(self, x):
        self.string = x

class B:
    def __init__(self,x):
        self.string = x

list_of_A_objects = get_large_list_of_A_objects()

list_of_B_objects = get_large_list_of_B_objects() 


for A_object in list_of_A_objects:
    for B_Object in list_of_B_objects:
        if A_object.string in B_Object.string:
            do_something()

【问题讨论】:

  • 做某事所需的时间并不是我所关心的。上面的代码是我的问题的简化示例。在我的真正问题中,随着一个列表变大,另一个列表也变大了,所以随着其中一个列表的大小增加,我会遇到 n^2 时间顺序的事情。
  • 我问因为找到第一个匹配项和做某事或寻找多个匹配项之间有很大的区别,我不认为 set 或 dict 可以帮助你寻找子字符串
  • 好的,我明白你的意思了。它需要搜索多个匹配项。谢谢
  • 对字符串有什么限制吗?如果它们是一般字符串,那么似乎很难比二次复杂度做得更好,但如果它们是特殊的,可能会有一些技巧。

标签: python performance algorithm search computer-science


【解决方案1】:

您可以做的一件事是从 B 对象创建单个字符串。在构建它时,您还创建了一个索引列表,因此您知道较大字符串中每个字符串的索引。请参阅下面的代码。

请注意,我不是 python 程序员,所以你必须解释我的伪代码。

BStrings = ""
list_of_Indexes = new list of int
for B_object in list_of_B_objects
    list_of_Indexes.Add(length of BStrings)
    BStrings = BStrings + B_Object.string + newline

现在,您可以搜索每个 A_object 的 BStrings 字符串。如果找到该字符串,该函数将返回在该字符串中找到它的位置的索引。然后,您可以对 list_of_indexes 进行二进制搜索以确定哪个 B_object 包含该字符串。

这并没有真正改变操作的复杂性(它仍然是 MxN,其中 M 是 A 列表中的对象数,N 是 B 列表的长度),但是在单个字符串中搜索子字符串会比遍历 B 列表更快,因为它避免了设置搜索的开销。

如果这太慢了,那么你会想要使用Aho-Corasick string matching algorithm 之类的东西。可能有一个不错的 Python 实现可用。

【讨论】:

  • 感谢您抽出宝贵时间回答,我会考虑一下。
【解决方案2】:

这是一个使用字典的 python 实现。首先将其中一个列表转换为由其对象字符串索引的列表

a_map = {}

for A_object in list_of_A_objects:
    a_map[A_object.string] = A_object

然后对于另一个列表中的每个对象,检查该对象的字符串是否存在于字典中(在恒定时间内),如果存在则do_something

for B_object in list_of_B_objects:
    if B_object.string in a_map:
        do_something(a_map[B_object.string])

这假设每个 A_object 都有一个唯一的字符串。如果不是这种情况,那么您可以将 a_map 的值设为对象数组而不是单个对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 2013-11-10
    • 2012-01-22
    • 1970-01-01
    相关资源
    最近更新 更多