Jonathan Edgardo
Jonathan Edgardo

Reputation: 513

Add linq property selector to Expression

I have the following Expression in Linq:

public static IEnumerable<T> NextDistinct<T>(this IEnumerable<T> items) 
{
    T previous = default(T);
    bool first = true;
    foreach(T item in items)
    {
        if (first || !Equals(previous, item)) 
        {
            first = false;
            previous = item;
            yield return item;
        }
    }
} 

I need to add a Selector like this:

.NextDistinct(i => i.articlepricehistory_sell)

I tried, but the key select doesn't work correctly:

public static IEnumerable<TSource> NextDistinct<TSource, TKey>(this IEnumerable<TSource> source,
            Func<TSource, TKey> keySelector)
        {
            TSource previous = default(TSource);
            bool first = true;
            foreach (TSource item in source)
            {
                if (first || !Equals(previous, item))
                {
                    first = false;
                    previous = item;
                    yield return item;
                }                
            }
        }

UPDATE:

This is my query i need to do a distinct only using the articlepricehistory_sell column

var ArticlesSellHistory = dt.AsEnumerable()
select new
{
   articlepricehistory_sell = articlespricehistory.Field<Double>("articlepricehistory_sell"),
   articlepricehistory_date = articlespricehistory.Field<DateTime>("articlepricehistory_date")
})
.NextDistinct(i => i.articlepricehistory_sell)
.ToList();

Result:

365 05/09/2015 02:30:31 p.m.
370 11/10/2015 04:19:37 p.m.
369.59  11/10/2015 04:19:54 p.m.
365 11/10/2015 04:20:05 p.m.
365 11/10/2015 04:20:58 p.m.
365 11/10/2015 04:33:22 p.m.

Expected Result:

365 05/09/2015 02:30:31 p.m.
370 11/10/2015 04:19:37 p.m.
369.59  11/10/2015 04:19:54 p.m.
365 11/10/2015 04:20:05 p.m.

Upvotes: 0

Views: 119

Answers (1)

Ivan Stoev
Ivan Stoev

Reputation: 205719

All you need is to replace TSource previous with TKey previousKey and compare it to the current item key (both extracted using the passed selector). Also it's good to allow optionally specifying a comparer for both your functions. The function in question could be like this

public static IEnumerable<TSource> NextDistinct<TSource, TKey>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector,
    IEqualityComparer<TKey> keyComparer = null)
{
    if (source == null) throw new ArgumentNullException("source");
    if (keySelector == null) throw new ArgumentNullException("keySelector");
    if (keyComparer == null) keyComparer = EqualityComparer<TKey>.Default;
    var previousKey = default(TKey);
    bool first = true;
    foreach (TSource item in source)
    {
        var itemKey = keySelector(item);
        if (first || !keyComparer.Equals(previousKey, itemKey))
        {
            yield return item;
            first = false;
            previousKey = itemKey;
        }
    }
}

Upvotes: 2

Related Questions