如何按搜索词数组的匹配次数对从Excel读取的句子列表排序
我手头有一个用于搜索的字符串数组,还有从Excel读取的句子列表。目前已经筛选出了列表中包含搜索词数组内任意词汇的句子,但现在需要根据词汇的匹配总次数对这些句子进行排序(匹配次数越多越靠前)。
示例说明
搜索词数组:
string[] srchList = {"smartphone" , "4GB" , "Amoled"}
从Excel读取的句子列表:
"Realme1 smartphone has super Amoled screen with 4GB RAM capacity."
"Realme2 smartphone has LCD screen with 4GB RAM capacity."
"Realme3 phone has LCD screen with 6GB RAM capacity."
"Realme4 phone has LED screen with 6GB RAM capacity."
"Realme5 smartphone has super Amoled screen with 4GB RAM and 4GB extended memory capacity"
筛选后的匹配句子:
"Realme1 smartphone has super Amoled screen with 4GB RAM capacity."(匹配3次)
"Realme2 smartphone has LCD screen with 4GB RAM capacity."(匹配2次)
"Realme5 smartphone has super Amoled screen with 4GB RAM and 4GB extended memory capacity."(匹配4次)
我需要把这些筛选后的句子按匹配次数从高到低排序,有没有简便的实现方法?
当前代码
foreach (DataRow row in rows) { if (null != row && row.ItemArray.Length > 0) { List<string> strRes = row.ItemArray.Where(itmArr => srchList.Any(wrd => itmArr.ToString().ToLower().Contains(wrd.ToString()))).OfType<string>().ToList(); if (null != strRes && strRes.Count > 0) { searchResult.AddRange(strRes); } } }
当然有更简洁高效的方法!我们可以把计算匹配次数、筛选有效句子、排序这三步用LINQ一次性完成,逻辑更清晰也更易维护。
核心思路是:
- 对每个句子,计算它包含所有搜索词的总出现次数(比如"4GB"出现两次就算两次)
- 过滤掉匹配次数为0的句子
- 按照匹配次数从高到低排序
改进后的代码示例
// 先把搜索词转成小写,避免重复转换,提升效率 var lowerSrchList = srchList.Select(w => w.ToLower()).ToList(); var sortedResults = rows .Where(row => row != null && row.ItemArray.Length > 0) .SelectMany(row => row.ItemArray.OfType<string>()) // 提取所有字符串类型的单元格内容 .Select(sentence => new { Sentence = sentence, MatchCount = lowerSrchList.Sum(wrd => // 统计每个搜索词在句子中的出现次数,用Regex.Escape处理特殊字符 Regex.Matches(sentence.ToLower(), Regex.Escape(wrd)).Count ) }) .Where(item => item.MatchCount > 0) // 筛选有匹配的句子 .OrderByDescending(item => item.MatchCount) // 按匹配次数降序排序 .Select(item => item.Sentence) // 只提取最终的句子内容 .ToList();
代码说明
- 统一转小写:提前把所有搜索词转成小写,避免每次判断都重复转换,减少不必要的性能消耗
- 精准统计次数:用
Regex.Matches统计每个搜索词在句子中的实际出现次数,求和得到总匹配数;Regex.Escape是为了兼容搜索词中可能包含的特殊符号(比如"4GB+"这类带特殊字符的词) - 链式逻辑处理:通过LINQ的链式调用一次性完成筛选、计数、排序,代码更简洁易读
如果你的需求是只要搜索词出现过就算1次,不管重复出现多少次,可以把MatchCount的计算改成下面这样:
MatchCount = lowerSrchList.Count(wrd => sentence.ToLower().Contains(wrd))
这样统计的是匹配到的不同搜索词的数量,根据你的实际需求选择即可。
内容的提问来源于stack exchange,提问作者Tech Learner

