HOW TO GET DISTINCT VALUES FROM THE LIST WITH LINQ

Recently I was working with data from a generic List 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:

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 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:

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:

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

PRINT | POSTED ON FRIDAY, MARCH 30, 2012 10:16 PM

This article is part of the GWB Archives. Original Author: gwbarchive

New on Geeks with Blogs

  • We Won The One Award I Actually Care About

    Full Scale made the Inc. 5000 for the fifth year straight, the 12th listing across my three companies. Here is why the one award you cannot buy is worth stopping for.

  • Your Customers Build the Features Now

    I let a tool I liked sit dead for a year rather than build the features I wanted. An MCP server meant I never had to, and your customers can do the same to your product.

  • Get the Size of a Directory in Linux the Easy Way

    du -sh for the quick answer, ncdu for the cleanup, df for the disk itself: every command for checking directory size in Linux, plus why du and df never agree.

  • Vim Search and Replace: The Ultimate Guide

    One :%s command replaces every match in a file before a find dialog would even open. The Vim substitute patterns worth the muscle memory: flags, ranges, capture groups, and multi-file edits.