订购自动填充功能

时间:2012-08-24 11:02:28

标签: c# linq autocomplete

我们假设我们收集了Human s:

public class Human
{
    public string FirstName { get; set; }
    public string SecondName { get; set; }
    public string CompanyName { get; set; }
}

var people = new List<Human>(){...};

我们如何在首先按FirstName然后按SecondName然后按CompanyName对人进行排序时实施自动完成功能?

我试过了:

people.Where(x => x.FirstName.StartsWith(term) || x.SecondName.StartsWith(term) 
  ||  x.CompanyName.StartsWith(term))
  .OrderBy(x => x.FirstName).ThenBy(x => x.SecondName).ThenBy(x => x.CompanyName)

但这并不能正常工作。我想首先只查看所有匹配的FirstName字段,然后只查看SecondName个字段,依此类推。

3 个答案:

答案 0 :(得分:4)

people.Where(x => x.FirstName.StartsWith(term)).OrderBy(x => x.FirstName)
.Concat(people.Where(x => x.SecondName.StartsWith(term)).OrderBy(x => x.SecondName))
.Concat(people.Where(x => x.CompanyName.StartsWith(term)).OrderBy(x => x.CompanyName))

根据您是否要排除一个人匹配的情况多于一种情况,将.Distinct()添加到最后(在这种情况下,您也可以使用.Union()代替{{1}取决于您的来源 - 它被记录为保留具有可枚举源的顺序,但不记录其他可查询源,因此它可能会根据.Concat()的来源搞乱排序。

答案 1 :(得分:2)

我想你会想要

people.Where(x => x.FirstName.StartsWith(term) ||
                  x.SecondName.StartsWith(term) ||
                  x.CompanyName.StartsWith(term))
    .OrderByDescending(x => x.FirstName.StartsWith(term))
    .ThenByDescending(x => x.SecondName.StartsWith(term))
    .ThenBy(x => x.FirstName)
    .ThenBy(x => x.SecondName)
    .ThenBy(x => x.CompanyName)

这就是

  • 名字首先匹配的所有人
  • 然后每个人的第二个名字都匹配
  • (然后,每个人的公司名称都匹配)
  • 在此顺序中,它将按照之前的第一个/最后一个/公司名称排序。

Descending小于false时,是/否排序需要true

你可以通过{{1}使用一个匿名类和SelectFirstNameMatches等三个bool来稍微优化一下,然后在{{1}中使用这些bool和订购子句,从而避免调用SecondNameMatches 5次而不是3次,但是当你对基本​​排序工作时你可以担心。

如果你想用秒名对第二名匹配进行排序,公司名称按公司名称匹配,那将会更加棘手。

答案 2 :(得分:2)

您所犯的错误是您在ThenBy()之后使用OrderBy()。使用此方法,您可以在内部对已经排序的列表进行重新排序,而无需根据属性是否匹配进行排序。

您应该做的是以三种方式过滤列表,然后加入它们并使用Union()删除重复项。

那么:

people.Where( x => x.FirstName.StartsWith( term ) ).OrderBy( x => x.FirstName )
      .Union( people.Where( x => x.SecondName.StartsWith( term ) ).OrderBy( x => x.SecondName ) )
      .Union( people.Where( x => x.CompanyName.StartsWith( term ) ).OrderBy( x => x.CompanyName ) );

编辑:

正如 Jon Hanna 指出的那样,如果您使用Queryable.Union(),这可能无效,因为它不会保留查询的顺序:

  

Enumerable.Union()被指定为保留顺序但是   Queryable.Union()不是。给定的实现可以,但事实并非如此   必须和另一个(或对同一个的更新)可能不会。代码   因此,如果有人,可以按任何顺序给出结果   不是内存中的来源。 Jon Hanna