tags:

views:

79

answers:

4

Hello,

I have a C# application that loads a List of CLR objects called "Tasks". Each Task has the following properties:

public int ID { get; set; }
public int TypeID { get; set; }
public string TypeName { get; set; }
public string Name { get; set; }

I am trying to find the unique types of tasks in this list. I thought I would try to use LINQ to do it. However, I cannot figure out how to do it. How do I say give me all of the unique TypeID and TypeName in this list? Currently I'm trying the following which is getting me no where. In fact, it wound even compile.

var uniqueTasks = allTasks.Distinct(p => p.TypeID);

Thank you,

+3  A: 

Let me make sure I understand the problem: you have a sequence of tasks called allTasks, and you would like a sequence without duplicates of all the ids, yes?

Transform the sequence of tasks into a sequence of ids:

var ids = allTasks.Select(p=>p.TypeId);

Now you have a sequence of ids. You wish to filter out the duplicates from that sequence:

var distinctIds = ids.Distinct();

And you're done. Is that what you were after?

Eric Lippert
A: 

You need to implement your own comparer:

public class TaskComparer : IEqualityComparer<Task>
{

    #region IEqualityComparer<Task> Members

    public bool Equals(Task x, Task y)
    {
        return x.TypeID == y.TypeID && x.TypeName == y.TypeName;
    }

    public int GetHashCode(Task obj)
    {
        return obj.TypeID.GetHashCode() + obj.TypeName.GetHashCode();
    }

    #endregion
}

Then use it like this:

var uniqueTasks = allTasks.Distinct(new TaskComparer());

EDIT: Hacked out some GetHashCode() thanks to Slaks who pointed out that GetHashCode is absolutely necessary (I guess it builds a HashTable internally)

BFree
WRONG WRONG WRONG! **You _MUST_ implement `GetHashCode`!**
SLaks
Really? Why's that?
BFree
Because otherwise, it will be completely useless.
SLaks
um... When is the Hash code *of the comparer* going to be important?
James Curran
@James: Love the sarcasm. However, it's not so far fetched to think that it calls the equals method to compare to items. I know now that it uses a HashTable internally...
BFree
he meant GetHashCode of the compared object.
@wwosik: Either way should do the trick...
BFree
You'll be comparing `Task` items, not `TaskComparer` items (which you only have one of anyway). Task needs a GetHashCode, not TaskComparer.
James Curran
@James: See here: http://msdn.microsoft.com/en-us/library/bb338049.aspx
BFree
What if the id or name are null? Computing a hash should not crash.
Eric Lippert
A: 

The simplest way to do this is to use GroupBy:

var uniqueTasks = allTasks.GroupBy(p => p.TypeID);

This will give you a set of groupings that map a TypeID to the tasks with that ID.

If you want a set of tasks, you can write

var uniqueTasks = allTasks.GroupBy(p => p.TypeID).Select(g => g.First());
SLaks
A: 
 var uniqueTasks = allTasks.Select(t=>t.TypeName).Distinct().ToList();
James Curran
t=>t.TypeName ;)
@wwosik... Thanks... I really should read the things I post...
James Curran