繁体   English   中英

如何有效地检查给定的字符串是否包含数组中的单词

[英]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。

如果性能非常重要,那么您也可以查看全文索引

Aho–Corasick字符串匹配算法

文章中有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;
}

基本上有两个优化要考虑

  • 将列表保存在内存中,无需不断对SQL进行操作
  • 使用二进制搜索来避免O(N * M)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM