Geeks With Blogs

News

Microsoft MVP


Moderator at CodeASP.NET


Quiz Master




free counters
Free counters
Added on January 19,2012


Follow Me @vmsdurano

A bit About Me



Disclaimer
The opinions expressed herein are my own personal opinions and does not represent the opinions of my employers. Nor does it represent the opinion of my dog, because I don’t have one.


Vinz' Blog (ProudMonkey) "Code, Beer and Music ~ my way of being a programmer"

Recently I was working with data from a generic List<T> and one of my objectives is to get the distinct values that is found in the List. Consider that we have this simple class that holds the following properties:

public class Product
{
        public string Make { get; set; }
        public string Model { get; set; } 

}

 

Now in the page code behind we will create a list of product by doing the following:

private List<Product> GetProducts() { 

    List<Product> products = new List<Product>(); 
    Product p = new Product(); 

    p.Make = "Samsung"; 
    p.Model = "Galaxy S 1"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Samsung"; 
    p.Model = "Galaxy S 2"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Samsung"; 
    p.Model = "Galaxy Note"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Apple"; 
    p.Model = "iPhone 4"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Apple"; 
    p.Model = "iPhone 4s"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "HTC"; 
    p.Model = "Sensation"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "HTC"; 
    p.Model = "Desire"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Nokia"; 
    p.Model = "Some Model"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Nokia"; 
    p.Model = "Some Model"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Sony Ericsson"; 
    p.Model = "800i"; 
    products.Add(p); 

    p = new Product(); 
    p.Make = "Sony Ericsson"; 
    p.Model = "800i"; 
    products.Add(p); 

    return products; 

}

 

And then let’s bind the products to the GridView.

protected void Page_Load(object sender, EventArgs e) { 
           if (!IsPostBack) { 
               Gridview1.DataSource = GetProducts();
               Gridview1.DataBind(); 
           } 
}

 

Running the code will display something like this in the page:

linq1

Now what I want is to get the distinct row values from the list. So what I did is to use the LINQ Distinct operator and unfortunately it doesn't work. In order for it work is you must use the overload method of the Distinct operator for you to get the desired results. So I’ve added this IEqualityComparer<T> class to compare values:

class ProductComparer : IEqualityComparer<Product> 
{ 
        public bool Equals(Product x, Product y) { 
            if (Object.ReferenceEquals(x, y)) return true; 

            if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) 
                return false; 

            return x.Make == y.Make && x.Model == y.Model; 
        } 

        public int GetHashCode(Product product) { 
            if (Object.ReferenceEquals(product, null)) return 0; 
            int hashProductName = product.Make == null ? 0 : product.Make.GetHashCode(); 
            int hashProductCode = product.Model.GetHashCode(); 
            return hashProductName ^ hashProductCode; 
        } 

}

 

After that you can then bind the GridView like this:

protected void Page_Load(object sender, EventArgs e) { 
            if (!IsPostBack) { 
                Gridview1.DataSource = GetProducts().Distinct(new ProductComparer()); 
                Gridview1.DataBind(); 
            } 
}

 

Running the page will give you the desired output below:

linq2

As you notice, it now eliminates the duplicate rows in the GridView. Now what if we only want to get the distinct values for a certain field. For example I want to get the distinct “Make” values such as Samsung, Apple, HTC, Nokia and Sony Ericsson and populate them to a DropDownList control for filtering purposes. I was hoping the the Distinct operator has an overload that can compare values based on the property value like (GetProducts().Distinct(o => o.PropertyToCompare). But unfortunately it doesn’t provide that overload so what I did as a workaround is to use the GroupBy,Select and First LINQ query operators to achieve what I want.

Here’s the code to get the distinct values of a certain field.

protected void Page_Load(object sender, EventArgs e) { 
            if (!IsPostBack) {
                DropDownList1.DataSource = GetProducts().GroupBy(o => o.Make).Select(o => o.First()); 
                DropDownList1.DataTextField = "Make"; 
                DropDownList1.DataValueField = "Model"; 
                DropDownList1.DataBind(); 
            } 

}

Running the code will display the following output below:

linq3

 

That’s it! I hope someone find this post useful!

Posted on Friday, March 30, 2012 10:16 PM | Back to top


Comments on this post: How to get distinct values from the List<T> with LINQ

# re: How to get distinct values from the List<T> with LINQ
Requesting Gravatar...
That seems a bit convoluted. How 'bout:

GetProducts().Select(o => o.Make).Distinct();
Left by James Curran on Apr 02, 2012 10:27 PM

# re: How to get distinct values from the List<T> with LINQ ..
Requesting Gravatar...
I agree with James if your need is only the Products with unique Make. However if your need is unique Make and Model, you can do this :
GetProducts().GroupBy(x => new { x.Make, x.Model }).Select(x => x.Key);
Left by Kishang Mi on Apr 03, 2012 2:49 PM

# re: How to get distinct values from the List<T> with LINQ
Requesting Gravatar...
Nice work!! Thanks for posting
Left by Jalpesh Vadgama on May 08, 2012 4:03 PM

# re: How to get distinct values from the List<T> with LINQ
Requesting Gravatar...
Nice example of using IEqualityComparer !!! Thanks for sharing
Left by Brij on Sep 07, 2012 5:19 PM

# re: How to get distinct values from the List<T> with LINQ
Requesting Gravatar...
like it !!!
good work :)
Left by alon on Sep 07, 2012 9:53 PM

# re: How to get distinct values from the List<T> with LINQ
Requesting Gravatar...
Love the IEqualityComparer example. Definitely my preference of direct line injection as suggested above. This way tends to be more robust when you can swap out the delegate at runtime. Also, more room for additional logic.

Getting into the habit of making these interfaces makes coding much more re-usable and readable . IComparer is great for sorting as well.
Left by James on Sep 08, 2012 3:03 AM

comments powered by Disqus

Copyright © Vincent Maverick Durano | Powered by: GeeksWithBlogs.net | Join free