C# 比较Linq

C# 比较Linq,c#,linq,C#,Linq,我在数据库中有一堆数据,我想为它们编写一个搜索函数。问题是我得到了很多复制品。 数据是以姓名和姓氏为结构的,我只想发送两种数据中唯一的一种,因此如果我有两个人的名字是Foo,姓氏栏中只会显示一个 不管我怎么想,我总是回到我需要比较它们的地方 var names = db.People .Where(r => r.Name.Contains(q)) .OrderBy(r=> r.Name) *Psuedo-Code* if((this

我在数据库中有一堆数据,我想为它们编写一个搜索函数。问题是我得到了很多复制品。 数据是以姓名和姓氏为结构的,我只想发送两种数据中唯一的一种,因此如果我有两个人的名字是Foo,姓氏栏中只会显示一个

不管我怎么想,我总是回到我需要比较它们的地方

var names = db.People
      .Where(r => r.Name.Contains(q))
      .OrderBy(r=> r.Name)
       *Psuedo-Code*
       if((this.Name==next.Name)&&(this.surSame==next.Surname)
           toss next data and loop to next
       *Psuedo-Code*
      .Take(5);
也许有点混乱,但你知道我想要实现什么。我可以用某种方式来实现这一点,还是有更好的方法来实现这一点?

使用
Distinct()
并在
人员
类中实现方法
Equals
,或者使用辅助类来比较它们:

public class PeopleComparer : IEqualityComparer<People>
{
    public bool Equals(People x, People y)
    {
        return x.Name == y.Name && x.Surname == y.Surname;
    }

    public int GetHashCode(People obj)
    {
        unchecked
        {
            return (obj.Name.GetHashCode() * 31) + obj.Surname.GetHashCode();
        }
    }
}
公共类PeopleComparer:IEqualityComparer
{
公共布尔等于(人x,人y)
{
返回x.Name==y.Name&&x.姓氏==y.姓氏;
}
公共int GetHashCode(人员对象)
{
未经检查
{
return(obj.Name.GetHashCode()*31)+obj.姓氏.GetHashCode();
}
}
}
您可以这样做:

var names = db.People
    .Where(r => r.Name.Contains(q))
    .Select(r => new { Name = r.Name, Surname = r.Surname })
    .Distinct()
    .Take(5);
但如果因为你需要全民记录而无法实现,你只需要第一个,我已经成功地完成了这样的工作:

var names = db.People
   .Where(r => r.Name.Contains(q))
   .GroupBy(r => new { Name = r.Name, Surname = r.Surname })
   .Select(g => g.First())
   .Take(5);

Distinct
People
类中使用
Equals
是正确的方法,但这里有一个更“内联”的替代方法:


听起来像是
。Distinct
可能适用于您的目的。是的,我已经尝试过了,但没有想到如何使用它。如果我的名字或姓氏不同,我只会得到一个。什么是
db
?或者:这是linq to sql吗?您还需要一个合理的
GetHashCode
实现。是的,我认为最好像现在这样将
GetHashCode
计算委托给
People
类。不,实际上,一点也不。事实上,这样做破坏了实现。哈希代码和等式必须基于同一个“东西”。散列代码应该基于姓名和姓氏,就像等式一样。好吧,我想你是想把代码移到
People
类,因为如果他实现
Equals
,那么
GetHashCode
计算应该是相同的。因此,第一个版本已经足够好了,因为它使用一个素数乘以第一个哈希代码。您还需要将
GetHashCode
的主体包装为
unchecked{…}
。看起来您的答案和我一样,快了1分钟。
new{Name=r.Name,lasname=r.lasname}
匿名类型声明实际上可以替换为更短但等效的
new{r.Name,r.lasname}
,如果您愿意的话。谢谢!我正要把我的笔记本电脑扔出窗外。我唯一需要做的改变是使用“FirstorDefault”,而不是使用其他函数的first。再次,非常感谢。这让我很开心!:)
var names = db.People
  .Where(r => r.Name.Contains(q))
  .GroupBy(r => new { r.Name, r.Surname })
  .Select(g => g.First())
  .OrderBy(r => r.Name)
  .Take(5);