1

I have a collection of classes and each class in the collection has three properties but need to distinct by two of the properties on the collection of classes. The confusing part is that I need all three properties after I distinct by only two of the properties. Most distinct by examples say to create an anonamous type using the properties you want to distinct by but that would get rid of my third property which I need to be in the collection of items after the distinct operation. How do I distinct by two of the three properties but the final result be a collection of the classes containing all three properties? Class is:

public class Foo
{
public int PropertyOne {get; set;}
public int PropertyTwo {get; set;}
public string PropertyThree {get; set;}
}

// fake example of what I want but
// final result has all three properties in the collection still
var finalResult = allItems.DistinctBy(i => i.PropertyOne, i.PropertyTwo).ToArray();

Thanks for any help!

Frekster
  • 1,138
  • 1
  • 14
  • 32
  • Did you actually try creating the anonymous type? It's only used as a key for grouping... the items in your src don't get projected into the output sequence using the lambda, they make it through unchanged. Try it. – spender Sep 07 '14 at 13:23
  • 1
    Why not create and IEqualityComparer and use LINQ's Distict method? – Tsef Sep 07 '14 at 13:25
  • 3
    @zaf: Creating an `IEqualityComparer` seems like a lot of overhead for something that can be stated as easily as `source.GroupBy(keySelector).Select(g => g.First())` – spender Sep 07 '14 at 13:30
  • Related to https://stackoverflow.com/questions/489258/linqs-distinct-on-a-particular-property – aloisdg Sep 13 '19 at 12:52

1 Answers1

6

If you look at the implementation of .DistinctBy :

    private static IEnumerable<TSource> DistinctByImpl<TSource, TKey>(IEnumerable<TSource> source,
        Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
    {
#if !NO_HASHSET
        var knownKeys = new HashSet<TKey>(comparer);
        foreach (var element in source)
        {
            if (knownKeys.Add(keySelector(element)))
            {
                yield return element;
            }
        }
#else
        //
        // On platforms where LINQ is available but no HashSet<T>
        // (like on Silverlight), implement this operator using
        // existing LINQ operators. Using GroupBy is slightly less
        // efficient since it has do all the grouping work before
        // it can start to yield any one element from the source.
        //

        return source.GroupBy(keySelector, comparer).Select(g => g.First());
#endif
    }

If you look at the !NO_HASHSET implementation... Notice how the element from the source is yielded unchanged...

Personally, I'd avoid morelinq altogether for this problem and just go with the second implementation directly:

allItems.GroupBy(i => new{i.PropertyOne, i.PropertyTwo}).Select(g => g.First())
spender
  • 117,338
  • 33
  • 229
  • 351
  • Thanks all for the responses. I went with the grouping suggestion - I did not realize that the third property would still be included after the grouping operation. – Frekster Sep 08 '14 at 12:56