将linq属性选择器添加到Expression

时间:2015-10-12 00:41:33

标签: c# .net linq collections

我在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;
        }
    }
} 

我需要像这样添加一个选择器:

.NextDistinct(i => i.articlepricehistory_sell)

我试过了,但是键选择不正常:

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;
                }                
            }
        }

更新

这是我的查询,我只需要使用articlepricehistory_sell列

进行区分
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();

结果:

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.

预期结果:

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.

1 个答案:

答案 0 :(得分:2)

您只需要将TSource previous替换为TKey previousKey,并将其与当前项密钥(使用传递的选择器提取)进行比较。同样可以选择为两个函数指定比较器,这样做很好。有问题的功能可能就像这样

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;
        }
    }
}