如何从List<T>中筛选属性恰好包含另一列表所有单词的项?
针对你的需求——从List<Sentence>中筛选出Description属性包含WordsList所有单词的项,我分两种常用场景来提供解决方案,同时考虑你后续要用到数据库的情况:
一、内存集合(Linq to Objects)
如果是在内存中处理List<Sentence>,直接用Linq的All方法就能实现核心逻辑——要求每个单词都能在Description中找到。
推荐:不区分大小写的匹配
避免因为大小写差异漏掉结果,比如"this"和"THIS"视为相同:
List<string> WordsList = new List<string> { "THIS", "CAT" }; List<Sentence> SentencesList = new List<Sentence> { new Sentence { Description = "THIS SENTENCE CONTAINS THE WORD DOG" }, new Sentence { Description = "THIS CAT IS PLAYING IN THE GARDEN" }, new Sentence { Description = "A CAT AND A DOG ARE HERE" } }; // 筛选出Description同时包含所有单词的项 var filteredSentences = SentencesList.Where(s => WordsList.All(word => s.Description.Contains(word, StringComparison.OrdinalIgnoreCase) ) ).ToList(); // 结果只会包含第二个项:"THIS CAT IS PLAYING IN THE GARDEN"
区分大小写的匹配
如果严格要求大小写完全一致,去掉StringComparison参数即可:
var filteredSentences = SentencesList.Where(s => WordsList.All(word => s.Description.Contains(word)) ).ToList();
二、数据库场景(Entity Framework Core/EF6)
当你把这段逻辑迁移到数据库查询时,要注意Linq to Entities的限制——不是所有内存中的方法都能被翻译成SQL,得调整写法适配数据库:
情况1:数据库 collation 不区分大小写
如果你的数据库(比如SQL Server)默认是不区分大小写的排序规则(如SQL_Latin1_General_CP1_CI_AS),直接用简单的Contains即可,EF会自动翻译成对应的SQL:
var filteredSentences = dbContext.Sentences .Where(s => WordsList.All(word => s.Description.Contains(word))) .ToList();
情况2:强制不区分大小写(兼容所有排序规则)
如果数据库区分大小写,或者你想确保逻辑不受数据库设置影响,可以用EF Core提供的EF.Functions.Like方法,或者统一转换为大小写:
// 方法1:使用Like(推荐,对索引更友好) var filteredSentences = dbContext.Sentences .Where(s => WordsList.All(word => EF.Functions.Like(s.Description, $"%{word}%") )) .ToList(); // 方法2:统一转换为小写(注意:可能会导致数据库无法使用索引,大数据量时谨慎) var lowerWords = WordsList.Select(w => w.ToLower()).ToList(); var filteredSentences = dbContext.Sentences .Where(s => lowerWords.All(word => s.Description.ToLower().Contains(word) )) .ToList();
额外:匹配独立单词的场景
如果你的需求是“包含独立单词”(比如CAT不能匹配CATAPULT),可以用正则表达式实现:
内存中实现
using System.Text.RegularExpressions; var filteredSentences = SentencesList.Where(s => WordsList.All(word => Regex.IsMatch(s.Description, $@"\b{Regex.Escape(word)}\b", RegexOptions.IgnoreCase) ) ).ToList();
数据库中实现(EF Core + SQL Server 2016+)
利用SQL Server的正则支持,通过EF.Functions.RegexIsMatch实现:
var filteredSentences = dbContext.Sentences .Where(s => WordsList.All(word => EF.Functions.RegexIsMatch(s.Description, $@"\b{Regex.Escape(word)}\b", RegexOptions.IgnoreCase.ToString()) )) .ToList();
内容的提问来源于stack exchange,提问作者Neill
相关产品推荐
相关产品推荐

