Python 列表搜索中的快速字符串
使用Python3,我有一个包含100000多个字符串(list1)的列表,每个字符串最多300个字符。我还有一个超过900万子字符串的列表(list2)——我想计算list2中的子字符串出现在其中的元素数。比如说,Python 列表搜索中的快速字符串,python,string,performance,list,Python,String,Performance,List,使用Python3,我有一个包含100000多个字符串(list1)的列表,每个字符串最多300个字符。我还有一个超过900万子字符串的列表(list2)——我想计算list2中的子字符串出现在其中的元素数。比如说, list1 = ['cat', 'caa', 'doa', 'oat'] list2 = ['at', 'ca', 'do'] 我希望函数返回(映射到列表2): 通常情况下,这是非常简单的,所需的资源非常少。然而,由于列表的巨大规模,我有效率问题。我想找到返回计数器列表的最快方法
list1 = ['cat', 'caa', 'doa', 'oat']
list2 = ['at', 'ca', 'do']
我希望函数返回(映射到列表2):
通常情况下,这是非常简单的,所需的资源非常少。然而,由于列表的巨大规模,我有效率问题。我想找到返回计数器列表的最快方法
我尝试过列表理解、生成器、地图、各种循环,但还没有找到一种快速的方法来完成这项简单的任务。从理论上讲,实现这一目标的最快方法是什么,最好是非常快地采取O(len(list2))
步骤?设置M=len(list1)
和N=len(list2)
对于list2
中的N个条目,您必须与list1
中的条目进行M个比较。这是最坏的运行时间O(mxn)
。如果你更进一步,让我们把list2
中的每个条目的长度设为1,把list1
中的每个条目的长度设为300,那么你得到的运行时间是O(300M x N)
如果性能确实是一个问题,请尝试动态编程。这是一个开始:
1) 按长度升序对列表2进行排序,如下所示:
['scorch', 'scorching', 'dump', 'dumpster', 'dumpsters']
2) 将其排序为子列表,使每个前一条目都是前一条目的子集,如下所示:
[['scorch', 'scorching'] , ['dump', 'dumpster', 'dumpsters']]
3) 现在,如果您与列表1
进行比较,并且'scorch'
不在其中,那么您也不必搜索'scorching'
。同样,如果'dump'
不在其中,则'dumpster'
或'dumpster'
注意,最坏情况下的运行时间仍然是相同的不确定如何避免使用某种O(n**2)算法。下面是一个简单的实现
>>> def some_sort_of_count(list1, list2):
>>> return [sum(x in y for y in list1) for x in list2]
>>>
>>> list1 = ['cat', 'caa', 'doa', 'oat']
>>> list2 = ['at', 'ca', 'do']
>>> some_sort_of_count(list1, list2)
[2, 2, 1]
我相信这个任务可以用机器在线性时间内解决。 有关更多信息,请参见答案(也许你也从该问题的其他答案中获得了一些想法-这几乎是同一个任务,我认为理论上,阿霍·科拉西克是解决这个问题的最快方法)
您必须以这样的方式修改字符串匹配机,即不是返回匹配,而是将每个匹配子字符串的计数器增加1。(这应该只是一个小的修改)。这是个好主意,但是列表2中的每个子字符串至少在列表1的一个元素中。这将需要大量的开销,但是您可以尝试根据它们所具有的字符对
list1
和list2
进行索引,因此,如果list1
的一个条目是'abcd'
,那么您不会检查list2
条目'efg'
,只有list2
条目属于'a'
、'b'
、'c'
或'd'
路径/分支,但会采取相同的步骤,对吗?现在,对于列表2中的每个子字符串,我都按sum计数(如果子字符串在字符串中,则列表1中的字符串为1)
。检查未包含的字符的过程不会花费与if/in语句相同的时间吗?@user1104160我可能弄错了,但我认为您无法避开最坏的情况O(300MxN)
。如果这是一个经常被调用的东西,我建议花点时间在一个巨大的树/数组中,根据长度和/或字母列表进行索引,我正试图为你创建一个小例子……伙计,这是一个多么糟糕的度过周五的方式啊
>>> def some_sort_of_count(list1, list2):
>>> return [sum(x in y for y in list1) for x in list2]
>>>
>>> list1 = ['cat', 'caa', 'doa', 'oat']
>>> list2 = ['at', 'ca', 'do']
>>> some_sort_of_count(list1, list2)
[2, 2, 1]