1

我需要实现一个过程,其中上传大约 50/150kb 的文本文件,并与大量短语(~10k)进行匹配。

我需要知道哪些短语特别匹配。

一个短语可以是“blah blah blah”或只是“blah”——这意味着我需要考虑单词边界,因为我不希望包含中缀匹配。

我的第一次尝试是创建一个大的预编译正则表达式列表,看起来像@"\b{0}\b"(因为 10k 短语是恒定的 - 我可以缓存并针对多个文档重复使用这个相同的列表);

在我全新且速度非常快的 PC 上 - 此匹配需要 10 秒以上,我希望能够减少很多。

任何关于我如何能够实现这一目标的建议将不胜感激!

干杯,戴夫

4

2 回答 2

1

您可以使用 Lucene.Net

这将为您的文本创建索引,以便您可以对其进行非常快速的查询。这是一个“全文索引”。

这篇文章解释了它的全部内容:

Lucene.net

这个库最初是用java(Lucene)编写的,但是有一个.NET(lucene.net)的端口。

选择词干分析器时必须特别小心。词干分析器获取单词的“词根”,以便可以匹配几个相似的单词(即 book 和 books 将匹配)。如果您需要完全匹配,那么您应该采用(或实施)一个词干分析器,它可以不加更改地返回原始单词。

必须使用相同的词干分析器来创建索引和搜索结果。

您还必须看一下语法,因为它太强大了,并且允许部分匹配、完全匹配等等。

你也可以看看这个博客

于 2012-09-13T10:46:04.400 回答
1

您可以使用 Lucene.NET 和Shingle 过滤器,只要您不介意限制短语可能包含的单词数量。

public class MyAnalyzer : Analyzer
{
    public override TokenStream TokenStream(string fieldName, TextReader reader)
    {       
        return new ShingleFilter(new LowerCaseFilter(new StandardTokenizer(Lucene.Net.Util.Version.LUCENE_29, reader)), 6);
    }
}

您可以使用此实用程序方法运行分析器。

public static IEnumerable<string> GetTerms(Analyzer analyzer, string keywords)
{
    var tokenStream = analyzer.TokenStream("content", new StringReader(keywords));
    var termAttribute = tokenStream.AddAttribute<ITermAttribute>();

    var terms = new HashSet<string>();

    while (tokenStream.IncrementToken())
    {
        var term = termAttribute.Term;
        if (!terms.Contains(term))
        {
            terms.Add(term);
        }
    }

    return terms;
}

一旦您检索到所有术语,请与您的单词列表相交。

var matchingShingles = GetTerms(new MyAnalyzer(), "Here's my stuff I want to match");

var matchingPhrases = phrasesToMatch.Intersect(matchingShingles, StringComparer.OrdinalIgnoreCase);

我想你会发现这种方法比正则表达式匹配要快得多,并且尊重单词边界。

于 2012-09-13T13:20:37.257 回答