我希望最终结果出现的顺序是“完全匹配”,首先给出一个输入字符串,然后是给定字段包含的其他匹配。我试图以一种非常基本的方式来解决这个问题,如本示例所示:
var raw = Model.SearchResults.Where(m => m.EffectiveDateTime != null).OrderBy(m => m.EffectiveDateTime).ToList();
var exact = raw.Where(m => m.IssueNumber.ToLower() == Model.SearchText.ToLower());
var contains = raw.Where(m => m.IssueNumber.ToLower().Contains(Model.SearchText.ToLower()));
var list = exact.Union(contains);
这种方法似乎是一种非常糟糕的方法。实际上,Union部分似乎有效地使我的应用程序崩溃了。与Intersection是否有对立面,它将为我提供完全匹配项之外的其余结果,然后我可以将其附加到最终列表中,从而使顺序为完全匹配项,然后是StartsWith匹配项,最后是包含该降序排列的匹配项?
答案 0 :(得分:1)
要回答您的原始问题,您可以使用一个临时表达式对匹配类型进行分类,然后按匹配类型和其他条件进行排序,它也将转换为SQL:
var st = Model.SearchText.ToLower();
var list = Model.SearchResults.Where(m => m.EffectiveDateTime != null)
.Select(m => new {
m,
im = m.IssueNumber.ToLower()
})
.Select(mim => new {
mim.m,
Rank = mim.im == st ? 1 : mim.im.StartsWith(st) ? 2 : mim.im.Contains(st) ? 3 : 4
})
.Where(mr => mr.Rank < 4)
.OrderBy(mr => mr.Rank)
.ThenBy(mr => mr.m.EffectiveDateTime)
.Select(mr => mr.m)
.ToList();
我做了两次Select
来模仿流利的语法let
,在这种情况下,我认为它比lambda语法更清楚:
var lisx = (from m in Model.SearchResults
where m.EffectiveDateTime != null
let im = m.IssueNumber.ToLower()
let Rank = im == st ? 1 : im.StartsWith(st) ? 2 : im.Contains(st) ? 3 : 4
where Rank < 4
orderby Rank, m.EffectiveDateTime
select m)
.ToList();
此外,如果您在数据库中进行整个查询,则ToLower
可能是不必要的,因为SQL的默认值可能不区分大小写。
答案 1 :(得分:0)
实际上,我回到了绘图板上并弄清楚了。这对我来说好一点,并返回我需要的结果。
var list = Model.SearchResults
.Where(e => e.A.ToLower().Contains(Model.SearchText.ToLower()))
.GroupBy(d => new { d.A, d.B, d.C})
.OrderBy(x => x.Key.A)
.ThenBy(x => x.Key.B)
.ThenBy(x => x.Key.C)
.Select(x => new
{
A= x.Key.A,
B= x.Key.B,
C= x.Key.C
})
.ToList();