Using .Select and .Where in a single LINQ statement

泄露秘密 提交于 2019-12-04 22:20:06

In order for Enumerable.Distinct to work for your type, you can implement IEquatable<T> and provide suitable definitions for Equals and GetHashCode, otherwise it will use the default implementation: comparing for reference equality (assuming that you are using a reference type).

From the manual:

The Distinct(IEnumerable) method returns an unordered sequence that contains no duplicate values. It uses the default equality comparer, Default, to compare values.

The default equality comparer, Default, is used to compare values of the types that implement the IEquatable generic interface. To compare a custom data type, you need to implement this interface and provide your own GetHashCode and Equals methods for the type.

In your case it looks like you might just need to compare the IDs, but you may also want to compare other fields too depending on what it means for you that two objects are "the same".

You can also consider using DistinctBy from morelinq.

Note that this is LINQ to Objects only, but I assume that's what you are using.

Yet another option is to combine GroupBy and First:

 var query = // your query here...
    .GroupBy(x => x.Id)
    .Select(g => g.First());

This would also work in LINQ to SQL, for example.

Flater

Did you add the Select() after the Where() or before?

You should add it after, because of the concurrency logic:

 1 Take the entire table  
 2 Filter it accordingly  
 3 Select only the ID's  
 4 Make them distinct.  

If you do a Select first, the Where clause can only contain the ID attribute because all other attributes have already been edited out.

Update: For clarity, this order of operators should work:

db.Items.Where(x=> x.userid == user_ID).Select(x=>x.Id).Distinct();

Probably want to add a .toList() at the end but that's optional :)

Since you are trying to compare two different objects you will need to first implement the IEqualityComparer interface. Here is an example code on a simple console application that uses distinct and a simple implementation of the IEqualityComparer:

 class Program
{
    static void Main(string[] args)
    {
        List<Test> testData = new List<Test>()
        {
            new Test(1,"Test"),
            new Test(2, "Test"),
            new Test(2, "Test")
        };

        var result = testData.Where(x => x.Id > 1).Distinct(new MyComparer());
    }
}

public class MyComparer : IEqualityComparer<Test>
{
    public bool Equals(Test x, Test y)
    {
        return x.Id == y.Id;
    }

    public int GetHashCode(Test obj)
    {
        return string.Format("{0}{1}", obj.Id, obj.Name).GetHashCode();
    }
}


public class Test
{
    public Test(int id, string name)
    {
        this.id = id;
        this.name = name;
    }

    private int id;

    public int Id
    {
        get { return id; }
        set { id = value; }
    }
    private string name;

    public string Name
    {
        get { return name; }
        set { name = value; }
    }
}

I hope that helps.

Do you passed a IEqualityComparer<T> to .Distinct()?

Something like this:

internal abstract class BaseComparer<T> : IEqualityComparer<T> {
    public bool Equals(T x, T y) {
        return GetHashCode(x) == GetHashCode(y);
    }

    public abstract int GetHashCode(T obj);
}

internal class DetailComparer : BaseComparer<StyleFeatureItem> {
    public override int GetHashCode(MyClass obj) {
        return obj.ID.GetHashCode();
    }
}

Usage:

list.Distinct(new DetailComparer())
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!