簡體   English   中英

檢查字符串列表中的所有元素是否都在字符串中的最快方法

[英]fastest way to check if all elements of a list of strings is in a string

我有一個字符串

“我的名字是安德魯,我非常棒”。

讓我們說我有一個列表,如

[['andrew','name','awesome'],['andrew','names','awesome']]

我需要我的解決方案才能回歸

['andrew','name','awesome']

天真的解決方案是:

myString='My name is Andrew, I am pretty awesome'
keywords = [['andrew', 'name', 'awesome'], ['andrew', 'designation', 'awesome']]
results=[]
for i in keywords:
 if all(substring in myString.lower() for substring in i):
    results.append(i)
print results

我的問題是,當列表關鍵字非常大(比如100000)時,存在性能瓶頸。 我需要知道最有效的方法。

感謝BlackBear 指出由於循環不變量的重新計算,我的時間偏差。 在將它們移出時,事情會發生巨大變化。

有兩種方法可以做到這一點。 理智的方式,以及正則表達方式。 首先,設置。

string = "My name is Andrew, I am pretty awesome"
choices = [['andrew', 'name', 'awesome'], ['andrew', 'designation', 'awesome']]

選項1
這個in列表解析中執行子字符串檢查。 in check在C語言中修改了Boyer-Moore算法的實現 ,並且非常快。

>>> [c for c in choices if all(y in string.lower() for y in c)]
[['andrew', 'name', 'awesome']]

現在,為了時間。 但首先,一個小的表現挑剔; 你可以在循環緩存string.lower()的值,它是一個不變量,不需要每次都重新計算 -

v = string.lower()
%timeit [c for c in choices if all(y in v for y in c)]
1000000 loops, best of 3: 2.05 µs per loop

選項2
這個使用re.split + set.issuperset ;

>>> import re
>>> [c for c in choices if set(re.split('\W', string.lower())).issuperset(c)] 
[['andrew', 'name', 'awesome']]

如果你想執行集合檢查,因為句子中的標點符號,無法避免使用re.split

同樣, set計算是循環不變量,可以移出。 這是它的作用 -

v = set(re.split('\W', string.lower()))
%timeit [c for c in choices if v.issuperset(c)] 
1000000 loops, best of 3: 1.13 µs per loop

這是一個例外情況,我發現正則表達式的執行速度略快。 但是,這些時間並不是決定性因素,因為數據的大小和結構差別很大。 我建議在得出任何結論之前用你自己的數據來解決問題,盡管我的直覺是正則表達式解決方案的擴展性很差。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM