如何对含字符串列表的对象按StartsWith优先排序LINQ搜索结果?
问题描述
我定义了如下C#类:
public class MyObject { public List<string> Names { get; set; } // other props }
现有初始化后的List<MyObject>集合,以及如下过滤逻辑:
var freeText = "comm"; var list = new List<MyObject>(); // Initialized var searchResult = list.Where(o => o.Names.Any(n => n.ToLower().StartsWith(freeText.ToLower())) || o.Names.Any(n => n.ToLower().Contains(freeText.ToLower())));
该过滤逻辑可正常工作,但我希望将搜索结果按匹配StartsWith的结果在前,匹配Contains的结果在后排序。例如:
Obj 1 {Names : [ "free communication" ,"some name"]}, Obj 2 { Names : ["communication Center", "whatever"]}
期望排序结果为[Obj2, Obj1]。我尝试过按freeText的索引排序,但不适用于字符串列表;也尝试修改相关方案,但未成功。请问如何实现该排序需求?
解决方案
你可以通过为匹配项分配优先级权重的方式实现排序:给满足StartsWith匹配的对象赋予更高优先级(比如0),仅满足Contains的对象赋予较低优先级(比如1),再按权重升序排序即可。
优化后的完整代码如下:
var freeTextLower = freeText.ToLower(); // 提前转小写,避免重复计算 var searchResult = list .Where(o => o.Names.Any(n => n.ToLower().Contains(freeTextLower))) // StartsWith是Contains的子集,简化过滤条件 .OrderBy(o => o.Names.Any(n => n.ToLower().StartsWith(freeTextLower)) ? 0 : 1) .ToList();
代码说明:
- 提前转小写:将搜索文本提前转为小写,避免在过滤和排序逻辑中重复执行
ToLower(),提升性能。 - 简化过滤条件:
StartsWith本质是Contains的特殊情况,因此过滤时只需判断是否存在Contains匹配项即可,逻辑更简洁。 - 优先级排序:通过三元表达式为不同匹配类型的对象分配优先级,优先级值越小越靠前,直接实现
StartsWith匹配项在前的需求。
如果需要同优先级内进一步排序(比如按匹配子串的位置排序),可以扩展如下:
var searchResult = list .Where(o => o.Names.Any(n => n.ToLower().Contains(freeTextLower))) .OrderBy(o => o.Names.Any(n => n.ToLower().StartsWith(freeTextLower)) ? 0 : 1) .ThenBy(o => o.Names.Min(n => n.ToLower().IndexOf(freeTextLower, StringComparison.OrdinalIgnoreCase) )) .ToList();
内容的提问来源于stack exchange,提问作者Mohamad Hammash
相关产品推荐
相关产品推荐

