tags:

views:

1961

answers:

3

Hi, I have the following item set from an XML:

id           category

5            1
5            3
5            4
5            3
5            3

I need a distinct list of these items:

5            1
5            3
5            4

How can I distinct for Category AND Id too in LINQ?

+8  A: 

Are you trying to be distinct by more than one field? If so, just use an anonymous type and the Distinct operator and it should be okay:

var query = doc.Elements("whatever")
               .Select(element => new {
                             id = (int) element.Attribute("id"),
                             category = (int) element.Attribute("cat") })
               .Distinct();

If you're trying to get a distinct set of values of a "larger" type, but only looking at some subset of properties for the distinctness aspect, you probably want DistinctBy as implemented in MoreLINQ in DistinctBy.cs:

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

(If you pass in null as the comparer, it will use the default comparer for the key type.)

Jon Skeet
Ah Why does it only work with anonymous type? If I have a class of Category and I say .Select(element => new Category {...}).Distinct(); it will not Distinct it at all.
balint
+1  A: 

Just use the Distinct() with your own comparer.

http://msdn.microsoft.com/en-us/library/bb338049.aspx

Stu
I've wrote my custom comparer, and it works fine, thanks!
balint
A: 

In addition to Jon Skeet's answer, you can also use the group by expressions to get the unique groups along w/ a count for each groups iterations:

var query = from e in doc.Elements("whatever")
            group e by new { id = e.Key, val = e.Value } into g
            select new { id = g.Key.id, val = g.Key.val, count = g.Count() };
James Alexander