4

假设我们有一个Humans 的集合:

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字段等等。

4

3 回答 3

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()而不是.Concat()取决于您的来源 - 它被记录为保留可枚举来源的顺序,但不是与其他可查询的来源,因此它可能会根据 ) 的来源弄乱排序people

于 2012-08-24T11:16:51.390 回答
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.

您可以通过使用带有 person 和三个 bool 等的匿名类来稍微优化这一点,Select然后在 and ordering 子句中使用这些 bool ,从而避免调用5 次而不是 3 次,但是当您有基本排序工作。FirstNameMatchesSecondNameMatchesWhereStartsWith

如果您想按第二名对第二名匹配进行排序,而按公司名称对公司名匹配进行排序,则会更加棘手。

于 2012-08-24T11:13:03.650 回答
2

你正在做的错误是你使用ThenBy()after 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() 不是。一个给定的实现可以,但它不是必须的,而另一个(或对同一实现的更新)可能不会。因此,如果 people 不是内存中的源,那么给出的代码可以以任何顺序给出结果。乔恩·汉纳

于 2012-08-24T11:33:52.947 回答