使用linq获取分组的日期范围

mko*_*mko 1 c# linq group-by

我有这个数据,我必须按价格分组,并检查数据的范围和连续性

date            price
2014-01-01  10
2014-01-02  10
2014-01-03  10
2014-01-05  20
2014-01-07  30
2014-01-08  40
2014-01-09  50
2014-01-10  30
Run Code Online (Sandbox Code Playgroud)

输出应该是这样的

2014-01-01  2014-01-03  10
2014-01-05  2014-01-05  20
2014-01-07  2014-01-07  30
2014-01-08  2014-01-08  40
2014-01-09  2014-01-09  50
2014-01-10  2014-01-10  30
Run Code Online (Sandbox Code Playgroud)

我到目前为止尝试过

 var result = list
                .OrderBy(a => a.Date)
                .GroupBy(a => a.Price)
                .Select(x => new
                {
                    DateMax = x.Max(a => a.Date),
                    DateMin = x.Min(a => a.Date),
                    Count = x.Count()
                })
                .ToList()
                .Where(a => a.DateMax.Subtract(a.DateMin).Days == a.Count)
                .ToList();
Run Code Online (Sandbox Code Playgroud)

我不确定这会照顾到连续的约会.所有日期都是独特的!

Ser*_*rvy 7

因此,首先我们将使用辅助方法对连续项进行分组.它将采用一个函数,该函数将被赋予"previous"和"current"项,然后它将确定该项是否应该在当前组中,或者应该启动一个新项.

public static IEnumerable<IEnumerable<T>> GroupWhile<T>(
    this IEnumerable<T> source, Func<T, T, bool> predicate)
{
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
            yield break;

        List<T> list = new List<T>() { iterator.Current };

        T previous = iterator.Current;

        while (iterator.MoveNext())
        {
            if (predicate(previous, iterator.Current))
            {
                list.Add(iterator.Current);
            }
            else
            {
                yield return list;
                list = new List<T>() { iterator.Current };
            }

            previous = iterator.Current;
        }
        yield return list;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以使用该方法对项目进行分组,然后选择我们需要的信息:

var query = data.OrderBy(item => item.Date)
                .GroupWhile((previous, current) => 
                    previous.Date.AddDays(1) == current.Date
                    && previous.Price == current.Price)
                .Select(group => new
                {
                    DateMin = group.First().Date,
                    DateMax = group.Last().Date,
                    Count = group.Count(),
                    Price = group.First().Price,
                });
Run Code Online (Sandbox Code Playgroud)