Coder Perfect

Using linq [duplicate], select distinct

Problem

I have a class schedule.

public class LinqTest
{
public int id { get; set; }
public string value { get; set; }
}


List<LinqTest> myList = new List<LinqTest>();
myList.Add(new LinqTest() { id = 1, value = "a" });
myList.Add(new LinqTest() { id = 1, value = "b" });
myList.Add(new LinqTest() { id = 2, value = "c" });

Only the separate ids from that list must be selected. i.e., my final list should only include

[{id=1,value="a"},{ id = 2, value = "c" }]

Is there a way to achieve this using Linq?

Edit

Input,

id      value
1        a
1        b
2        c
3        d
3        e

The final product should be,

id      value
1        a
2        c
3        d

If id occurs more than once, the result should only use the first occurrence.

Asked by Anoop Joshi P

Solution #1

myList.GroupBy(test => test.id)
      .Select(grp => grp.First());

Edit: Because converting this IEnumerable> to a List> appears to be a surprise to many people, you can just write:

var result = myList.GroupBy(test => test.id)
                   .Select(grp => grp.First())
                   .ToList();

However, working with the IEnumerable rather than the IList is generally preferable because the Linq above is lazy: it doesn’t actually do all of the work until the enumerable is iterated. When you call ToList, it walks through the full enumerable, forcing you to do all of the work up front. (And it can take a while if your enumerable is infinite.)

The disadvantage of this advise is that every time you enumerate such an IEnumerable, you must re-evaluate it. As a result, you must decide whether it is best to work with the lazily evaluated IEnumerable or to convert it to a List, Set, Dictionary, or something else in each circumstance.

Answered by Paul Ruane

Solution #2

You can use DistinctBy: with morelinq.

myList.DistinctBy(x => x.id);

Otherwise, you can use a group

myList.GroupBy(x => x.id)
      .Select(g => g.First());

Answered by Daniel Hilgarth

Solution #3

You should meaningfully override Equals and GetHashCode in this case to compare the ID:

public class LinqTest
{
    public int id { get; set; }
    public string value { get; set; }

    public override bool Equals(object obj)
    {
        LinqTest obj2 = obj as LinqTest;
        if (obj2 == null) return false;
        return id == obj2.id;
    }

    public override int GetHashCode()
    {
        return id;
    }
}

You can now use Distinct:

List<LinqTest> uniqueIDs = myList.Distinct().ToList();

Answered by Tim Schmelter

Solution #4

myList.GroupBy(i => i.id).Select(group => group.First())

Answered by Tim Rogers

Post is based on https://stackoverflow.com/questions/19406242/select-distinct-using-linq