[c#] linq query to return distinct field values from a list of objects

class obj
{
    int typeId; //10 types  0-9 
    string uniqueString; //this is unique
}

Assume there is list with 100 elements of obj, but only 10 unique typeIDs.
Is it possible to do write a LINQ query return the 10 unique ints from the list of objs?

This question is related to c# linq

The answer is


I think this is what your looking for:

    var objs= (from c in List_Objects 
orderby c.TypeID  select c).GroupBy(g=>g.TypeID).Select(x=>x.FirstOrDefault());      

Similar to this Returning a Distinct IQueryable with LINQ?


If just want to user pure Linq, you can use groupby:

List<obj> distinct =
  objs.GroupBy(car => car.typeID).Select(g => g.First()).ToList();

If you want a method to be used all across the app, similar to what MoreLinq does:

public static IEnumerable<TSource> DistinctBy<TSource, TKey>
    (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
    HashSet<TKey> seenKeys = new HashSet<TKey>();
    foreach (TSource element in source)
    {
        if (!seenKeys.Contains(keySelector(element)))
        {
            seenKeys.Add(keySelector(element));
            yield return element;
        }
    }
}

Using this method to find the distinct values using just the Id property, you could use:

var query = objs.DistinctBy(p => p.TypeId);

you can use multiple properties:

var query = objs.DistinctBy(p => new { p.TypeId, p.Name });

If just want to use Linq, you can override Equals and GetHashCode methods.

Product class:

public class Product
{
    public string ProductName { get; set; }
    public int Id { get; set; }


    public override bool Equals(object obj)
    {
        if (!(obj is Product))
        {
            return false;
        }

        var other = (Product)obj;
        return Id == other.Id;
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }
}

Main Method:

static void Main(string[] args)
    {

        var products = new List<Product>
        {
            new Product{ ProductName="Product 1",Id = 1},
            new Product{ ProductName="Product 2",Id = 2},
            new Product{ ProductName="Product 4",Id = 5},
            new Product{ ProductName="Product 3",Id = 3},
            new Product{ ProductName="Product 4",Id = 4},
            new Product{ ProductName="Product 6",Id = 4},
            new Product{ ProductName="Product 6",Id = 4},
        };

        var itemsDistinctByProductName = products.Distinct().ToList();

        foreach (var product in itemsDistinctByProductName)
        {
            Console.WriteLine($"Product Id : {product.Id} ProductName : {product.ProductName} ");
        }

        Console.ReadKey();
    }

Sure, use Enumerable.Distinct.

Given a collection of obj (e.g. foo), you'd do something like this:

var distinctTypeIDs = foo.Select(x => x.typeID).Distinct();

I wanted to bind a particular data to dropdown and it should be distinct. I did the following:

List<ClassDetails> classDetails;
List<string> classDetailsData = classDetails.Select(dt => dt.Data).Distinct.ToList();
ddlData.DataSource = classDetailsData;
ddlData.Databind();

See if it helps


Assuming you want the full object, but only want to deal with distinctness by typeID, there's nothing built into LINQ to make this easy. (If you just want the typeID values, it's easy - project to that with Select and then use the normal Distinct call.)

In MoreLINQ we have the DistinctBy operator which you could use:

var distinct = list.DistinctBy(x => x.typeID);

This only works for LINQ to Objects though.

You can use a grouping or a lookup, it's just somewhat annoying and inefficient:

var distinct = list.GroupBy(x => x.typeID, (key, group) => group.First());