如何使用"Linq to Objects"将一组连续的日期放在一组中? [英] How can I use "Linq to Objects" to put a set of contiguous dates in one group?
问题描述
我有一个麻烦的查询要写.我目前正在写一些讨厌的for循环来解决它,但我很好奇Linq是否可以为我做这件事.
I have a troublesome query to write. I'm currently writing some nasty for loops to solve it, but I'm curious to know if Linq can do it for me.
我有:
struct TheStruct
{
public DateTime date {get; set;} //(time portion will always be 12 am)
public decimal A {get; set;}
public decimal B {get; set;}
}
以及包含这些结构的列表.假设它是这样订购的:
and a list that contains these structs. Let's say it's ordered this way:
List<TheStruct> orderedList = unorderedList.OrderBy(x => x.date).ToList();
如果将orderedList结构日期放入集合中,则它们相对于日期将始终是连续的.也就是说,如果列表中的最新日期是2011/01/31,并且列表中最早的日期是2011 /01/01,那么您会发现列表中包含31个项目,一月的每个日期都包含一个项目.
If you put the orderedList struct dates in a set they will always be contiguous with respect to the day.. that is if the latest date in the list was 2011/01/31, and the earliest date in the list was 2011/01/01, then you'd find that the list would contain 31 items, one for each date in January.
好,所以我想对列表项进行分组,例如:
Ok, so what I want to do is group the list items such that:
- 组中的每个项目必须包含相同的十进制A值和相同的十进制B值
- 如果日期值按顺序排列,则组中的日期值必须形成一组连续的日期
- 如果您将每个组中的项目总数相加,则总数将等于原始列表中的项目数(或者您可以说具有特定日期的结构不能属于多个组) li>
任何Linq大师都知道该怎么做?
Any Linq masters know how to do this one?
谢谢!
推荐答案
您可以使用 GroupAdjacent扩展方法将序列中的相邻项目分组(见下文):
You can group adjacent items in a sequence using the GroupAdjacent Extension Method (see below):
var result = unorderedList
.OrderBy(x => x.date)
.GroupAdjacent((g, x) => x.A == g.Last().A &&
x.B == g.Last().B &&
x.date == g.Last().date.AddDays(1))
.ToList();
示例:
(1,1) 2011-01-01 \
(1,1) 2011-01-02 > Group 1
(1,1) 2011-01-03 __/
(2,1) 2011-01-04 \
(2,1) 2011-01-05 > Group 2
(2,1) 2011-01-06 __/
(1,1) 2011-01-07 \
(1,1) 2011-01-08 > Group 3
(1,1) 2011-01-09 __/
(1,1) 2011-02-01 \
(1,1) 2011-02-02 > Group 4
(1,1) 2011-02-03 __/
扩展方法:
static IEnumerable<IEnumerable<T>> GroupAdjacent<T>(
this IEnumerable<T> source, Func<IEnumerable<T>, T, bool> adjacent)
{
var g = new List<T>();
foreach (var x in source)
{
if (g.Count != 0 && !adjacent(g, x))
{
yield return g;
g = new List<T>();
}
g.Add(x);
}
yield return g;
}
这篇关于如何使用"Linq to Objects"将一组连续的日期放在一组中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!