繁体   English   中英

如何从C#中的LINQ查询中获取不同的项目?

[英]How to get distinct items from a LINQ query in C#?

我有一个查询,它的定义是这样的,我用它来生成JSON输出。 关键是,我已经对其应用了Distinct方法,但是它仍然显示重复项。 例如,我有许多项的值为“未分类”,而我只想要其中一项,其他一些值也是如此。 这是我的查询:

var results = db.Users.OfType<Business>()
              .Where(b => b.StateID == state && (term == null || b.Description.ToLower().Contains(term.ToLower())))
              .Distinct().Select(x => new { id = x.StateID, value = x.Description }).Take(5).ToList();

任何想法,如何解决? 我想我需要以某种方式专门将Distinct应用于该值。

我怀疑您需要切换“非Distinct和“ Select呼叫。 Distinct将比较比给定投影可能期望的更多字段,这可能意味着正在比实际要比较的字段进行比较。 首先调用“ Select将减少进行比较以生成唯一列表的字段数。

var results = db.Users.OfType<Business>()
          .Where(b => b.StateID == state && (term == null ||  b.Description.ToLower().Contains(term.ToLower())))
          .Select(x => new { id = x.StateID, value = x.Description })
          .Distinct()
          .Take(5)
          .ToList();

.NET无法知道您如何确定对象中的“平等”。 默认情况下,引用类型的相等性仅基于引用相等性,因此默认情况下,所有对象都是不同的。

您可以为Distinct()提供一个自定义的相等比较器 例如,如果您只是在比较.Name属性以确定唯一性,它可能看起来像这样:

class BusinessComparer : IEqualityComparer<Business>
{
    public bool Equals(Business x, Business y)
    {
        if (Object.ReferenceEquals(x, y))
            return true;
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;
        return x.Name == y.Name;
    }

    public int GetHashCode(Business business)
    {
        if (Object.ReferenceEquals(business, null))
            return 0;
        int hashBusinessName = business.Name == null ? 0 : business.Name.GetHashCode();
        return hashProductName;
    }
}

如果这种平等是核心业务逻辑,而不仅仅是在特定的比较中使用,则您甚至可以在Business本身上实现EqualsGetHashCode ,以便可以在其他地方使用平等比较。 请注意,这可能是对已经假定引用相等的现有代码的重大更改。

Business类需要重写object.Equalsobject.GetHashCode方法和实现IEquatable<T>前的Distinct方法将正常工作。

请参见MSDN示例: Enumerable.Distinct方法(IEnumerable)

通过使用默认的相等比较器比较值, Distinct()返回序列中的不同元素。 因此,您应该创建BusinessEqualityComparer类,并应实现IEqualityComparer接口

class BusinessEqualityComparer : IEqualityComparer<Business>
{

    public bool Equals(Business b1, Business b2)
    {
        if (b1.ID == b2.ID)
        {
            return true;
        }
        else
        {
            return false;
        }
    }


    public int GetHashCode(Business business)
    {
        int hCode = business.ID ^ business.ID ^ business.ID;
        return hCode.GetHashCode();
    }

不提供手动比较器的.Distinct()将使用已处理类型的默认比较器,该类型将最终使用您的Business类的.Equals().GetHashCode()

因此,除非您重写了这些方法, .Distinct()将仅删除引用方式的重复项。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM