LINQ统计出现次数

3

我有一个很好用的查询:

string[] Words = {"search","query","example"};

... Snip ...

var Results = (
    from a in q
    from w in Words
    where
        (
        a.Title.ToLower().Contains(w)
        || a.Body.ToLower().Contains(w)
        )
    select new
    {
        a,
        Count = 0
    }).OrderByDescending(x=> x.Count)
    .Distinct()
    .Take(Settings.ArticlesPerPage);

我需要它返回“Count”的值,即单词的总出现次数。我会偏向于标题,例如:
Count = (OccuranceInTitle * 5) + (OccurancesInBody)

我认为我需要使用Linq.Count,但我不确定如何在这种情况下应用它。

1个回答

5
这是我想到的东西:
var query =
    from a in q
    from w in Words
    let title = a.Title.ToLower()
    let body = a.Body.ToLower()
    let replTitle = Regex.Replace(title, string.Format("\\b{0}\\b", w), string.Empty)
    let replBody = Regex.Replace(body, string.Format("\\b{0}\\b", w), string.Empty)
    let titleOccurences = (title.Length - replTitle.Length) / w.Length
    let bodyOccurences = (body.Length - replBody.Length) / w.Length
    let score = titleOccurences * 5 + bodyOccurences
    where score > 0
    select new { Article = a, Score = score };

var results = query.GroupBy(r => r.Article)
                   .OrderByDescending(g => g.Sum(r => r.Score))
                   .Take(Settings.ArticlesPerPage);

计算出现次数的方法是使用快速且简单的方法,将出现次数替换为string.Empty,并基于结果字符串长度进行计算。在计算每篇文章和每个单词的分数后,我会对每篇文章进行分组,按所有单词的分数总和排序,并从结果中取出一部分。

由于没有启动编译器,请原谅任何明显的错误。

更新:此版本使用正则表达式,如下所示:

Regex.Replace(title, string.Format("\\b{0}\\b", w), string.Empty)

与原版本不同的是

title.Replace(w, string.Empty)

现在它只匹配整个单词(使用string.Replace则会匹配单词片段)。


哦,很好,这很聪明!它甚至自然地更加重视长单词,我喜欢它!只是为了确认一下,title.Replace(w, string.Empty)会使用一个单词数组吗? - Tom Gullen
@Jason:干得好。这可以通过使用 Regex.Replace 而不是 string.Replace 来修复 - 我会解决的。 - Jon
我已经通过去掉停用词过滤了单词(因此搜索“a file”将搜索“file”),并且在我的应用程序中,“Bookkeepers”中的“Book”匹配也是可以的。 - Tom Gullen
@TomGullen:与此同时,我已经切换到使用“\b”来定位单词边界的Regex.Replace,因此现在它只匹配整个单词 :) - Jon
@Jon,我有几个查询出现了除以0的错误,你知道在linq中解决这个问题的方法吗? - Tom Gullen
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接