Distinct Favor Latter

The default LINQ Distinct implementation returns the first of the duplicate items,

static IEnumerable<TSource> DistinctIterator<TSource>

(IEnumerable<TSource> source, IEqualityComparer<TSource> comparer) { Set<TSource> set = new Set<TSource>(comparer); foreach (TSource element in source) if (set.Add(element)) yield return element; }

Ran into a situation where I needed distinct elements based on some property and wanted to prefer the last item if duplicates are found. Turned out to be quiet simple:

public static IEnumerable<TSource> DistinctFavorLatter<TSource, TKey>
    (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
    return source.ToLookup(keySelector).Select(group => group.Last());
}

A simple unit test:

[Test]
public void DistinctFavourLatter()
{
    var source = new List<Pair<int, char>>
                     {
                         new Pair<int, char>(1, 'a'),
                         new Pair<int, char>(2, 'b'),
                         new Pair<int, char>(3, 'c'),
                         new Pair<int, char>(4, 'd'),
                         new Pair<int, char>(2, 'e'),
                         new Pair<int, char>(4, 'f'),
                         new Pair<int, char>(5, 'g')
                     };

    var actual = source.DistinctFavorLatter(item => item.First);

    var expected = new List<Pair<int, char>>
                     {
                         new Pair<int, char>(1, 'a'),
                         new Pair<int, char>(3, 'c'),
                         new Pair<int, char>(2, 'e'),
                         new Pair<int, char>(4, 'f'),
                         new Pair<int, char>(5, 'g')
                     };

    CollectionAssert.AreEquivalent(expected, actual);
}
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s