![](/img/trans.png)
[英]How to find all occurrences of a list of strings in a string and return a list of list of int in python?
[英]Python - find occurrences of list of strings within string
我有一個大字符串和一個搜索字符串列表,並希望構建一個布爾列表,指示每個搜索字符串是否存在於大字符串中。 在Python中執行此操作的最快方法是什么?
下面是一個使用天真方法的玩具示例,但我認為這可能是一種更有效的方法。
例如,下面的示例應返回[1,1,0],因為測試字符串中存在“hello”和“world”。
def check_strings(search_list, input):
output = []
for s in search_list:
if input.find(s) > -1:
output.append(1)
else:
output.append(0)
return output
search_strings = ["hello", "world", "goodbye"] test_string = "hello world" print(check_strings(search_strings, test_string))
我不能說這是否是最快的 (這仍然是O(n * m)),但這是我這樣做的方式:
def check_strings(search_list, input_string):
return [s in input_string for s in search_list]
以下程序可能更快或更快。 它使用正則表達式來傳遞一個輸入字符串。 請注意,您可能希望在re.findall()
表達式中使用re.escape(i)
,具體取決於您的需要。
def check_strings_re(search_string, input_string):
import re
return [any(l)
for l in
zip(*re.findall('|'.join('('+i+')' for i in search_string),
input_string))]
這是一個完整的測試程序:
def check_strings(search_list, input_string):
return [s in input_string for s in search_list]
def check_strings_re(search_string, input_string):
import re
return [any(l)
for l in
zip(*re.findall('|'.join('('+i+')' for i in search_string),
input_string))]
search_strings = ["hello", "world", "goodbye"]
test_string = "hello world"
assert check_strings(search_strings, test_string) == [True, True, False]
assert check_strings_re(search_strings, test_string) == [True, True, False]
使用Aho Corasick算法( https://pypi.python.org/pypi/pyahocorasick/ )的實現,它使用單個字符串傳遞:
import ahocorasick
import numpy as np
def check_strings(search_list, input):
A = ahocorasick.Automaton()
for idx, s in enumerate(search_list):
A.add_word(s, (idx, s))
A.make_automaton()
index_list = []
for item in A.iter(input):
index_list.append(item[1][0])
output_list = np.array([0] * len(search_list))
output_list[index_list] = 1
return output_list.tolist()
search_strings = ["hello", "world", "goodbye"]
test_string = "hello world"
print(check_strings(search_strings, test_string))
我發布它只是為了比較。 我的比較代碼:
#!/usr/bin/env python3
def gettext():
from os import scandir
l = []
for file in scandir('.'):
if file.name.endswith('.txt'):
l.append(open(file.name).read())
return ' '.join(l)
def getsearchterms():
return list(set(open('searchterms').read().split(';')))
def rob(search_string, input_string):
import re
return [any(l)
for l in
zip(*re.findall('|'.join('('+i+')' for i in search_string),
input_string))]
def blotosmetek(search_strings, input_string):
import re
regexp = re.compile('|'.join([re.escape(x) for x in search_strings]))
found = set(regexp.findall(input_string))
return [x in found for x in search_strings]
def ahocorasick(search_list, input):
import ahocorasick
import numpy as np
A = ahocorasick.Automaton()
for idx, s in enumerate(search_list):
A.add_word(s, (idx, s))
A.make_automaton()
index_list = []
for item in A.iter(input):
index_list.append(item[1][0])
output_list = np.array([0] * len(search_list))
output_list[index_list] = 1
return output_list.tolist()
def naive(search_list, text):
return [s in text for s in search_list]
def test(fn, args):
start = datetime.now()
ret = fn(*args)
end = datetime.now()
return (end-start).total_seconds()
if __name__ == '__main__':
from datetime import datetime
text = gettext()
print("Got text, total of", len(text), "characters")
search_strings = getsearchterms()
print("Got search terms, total of", len(search_strings), "words")
fns = [ahocorasick, blotosmetek, naive, rob]
for fn in fns:
r = test(fn, [search_strings, text])
print(fn.__name__, r*1000, "ms")
我使用Leviathan中出現的不同單詞作為搜索詞,並將來自Project Gutenberg的25個最常下載的書籍連接為搜索字符串。 結果如下:
Got text, total of 18252025 characters
Got search terms, total of 12824 words
ahocorasick 3824.111 milliseconds
Błotosmętek 360565.542 milliseconds
naive 73765.67 ms
Robs版本已經運行了大約一個小時但仍未完成。 也許它已經壞了,也許它只是非常緩慢。
我的版本使用正則表達式:
def check_strings(search_strings, input_string):
regexp = re.compile('|'.join([re.escape(x) for x in search_strings]))
found = set(regexp.findall(input_string))
return [x in found for x in search_strings]
在原始海報提供的測試數據上,它比Rob的漂亮解決方案慢了一個數量級,但我將對更大的樣本做一些基准測試。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.