[英]How to efficiently check if a given string contains words from an array
我正在构建一个用户在其中输入文本块的应用程序。 提交后,我需要检查该文本块是否包含预定义单词列表中的单词。
单词列表很大,大约是50K,所以我需要找出一种可以高效,快速地进行检查的方法。
这是我已经想过的一些解决方案,但是它们似乎效率很低
选项1:在App的代码中创建一个功能,该功能仅循环遍历每个预定义的单词并检查该单词是否在文本块中
例如
var wordList = ['fox','dog','tree']; //in my app this list will be large
function contains(userInput) {
for(i in wordList){
if(userInput.indexOf(wordList[i]) > -1)
return true;
}
return false
}
选项2:文本和单词列表块都将存储在数据库中,因此我可以执行这样的SQL语句
例如
SELECT *
FROM UserInput ui
INNER JOIN WordList wl ON wl.word LIKE CONCAT('%', ui.InputText, '%')
有一个更好的方法吗?
如果您要查看的数据大于小型数据集(可以验证50k),那么我肯定会在数据库中进行任何数据处理。
您是正确的,开放式LIKE
性能不会很差,但是它比在数据库外部执行时要快几个数量级。 如果保证您的用户输入是完整单词,那么您可以将WordList
中的所有内容WordList
为单独的单词,然后进行精确匹配搜索。 如果不能保证从UserInput
获得完整的单词,那么我将使用您的选项2。
如果性能非常重要,那么您也可以查看全文索引
文章中有C#实现的链接。
您可以在数据库中或使用LINQ进行此操作。
在空格上分割用户输入,以便您有一个包含用户输入字的数组或表值参数。 然后对您的单词列表进行内部联接。 联接之后剩下的所有内容都是在两个地方都存在的单词。 性能将非常出色。
SELECT SomeColumn
FROM WordList wl
JOIN @tvp ui ON wl.SomeColumn = ui.SomeColumn
它比进行LIKE搜索要快几个数量级,并且比全文本索引要容易得多。
我肯定会在应用程序端这样做。但是我将列表假定为“坏词”列表,并且它不会经常更改..如果假设是正确的,那么代码将类似于这个
static List<String> Chached;
List<String> GetBadWords()
{
if(Chached==null)
{
//load words from db into static array
Chached.Sort();//!important step
}
return Chached
}
public bool IstextValid(String sText)
{
List<String> oBadWords = GetBadWords()
foreach(String sWord in Rexex.Split(sText,@"\W"))//split by anything not alphanumeric
if(oBadWords.BinarySearch(sWord )>=0)//since is sorted we can do binary search O(log n)
return false;
return true;
}
基本上有两个优化要考虑
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.