C# 创建包含缺少的键的分组
我有一个C# 创建包含缺少的键的分组,c#,linq,grouping,C#,Linq,Grouping,我有一个IEnumerable,其中有一个创建的字段,它是一个日期。 每个日期可以有多个T,有时给定日期没有T 目前,我正在按日期对这些数据进行分组,这将为我提供至少有一个T的所有日期,以及它们下面的T 不过,我想要的是,我可以将其用作查询的一部分,以获取某个范围内的所有日期,而不管给定日期是否有T 当前代码: var adjustments = DAL.GetAdjustmentsInDateRange(Start, End); from adjustment in adjustments
IEnumerable
,其中有一个创建的
字段,它是一个日期。每个日期可以有多个
T
,有时给定日期没有T
目前,我正在按日期对这些数据进行分组,这将为我提供至少有一个T
的所有日期,以及它们下面的T
不过,我想要的是,我可以将其用作查询的一部分,以获取某个范围内的所有日期,而不管给定日期是否有T
当前代码:
var adjustments = DAL.GetAdjustmentsInDateRange(Start, End);
from adjustment in adjustments
group adjustment by adjustment.Created.Date into adjustmentsByDay
orderby adjustmentsByDay.Key descending
select ....
在这里,调整工作日
并非所有日期都在开始
和结束
之间。我想要的是它包含它们,没有任何元素。
我该怎么做呢?在分组之前,您可以将所有日期的列表留给join adjustments,如下所示:
var adjustments = DAL.GetAdjustmentsInDateRange(Start, End);
// Get all unique dates in time span
IEnumerable<DateTime> dates = GetAllDates(Start, End);
var query = (from date in dates
join adjustment in adjustments
on date.Date equals adjustment.Created.Date into a
from adjustment in a.DefaultIfEmpty()
select new {date.Date, adjustment}
).GroupBy(i=>i.Date).OrderBy(g=>g.Key);
var adjustments=DAL.GetAdjustmentsInDateRange(开始、结束);
//获取时间跨度中的所有唯一日期
IEnumerable dates=GetAllDates(开始、结束);
变量查询=(日期中的起始日期)
在调整中加入调整
日期。日期等于调整。创建。日期
从a.DefaultIfEmpty()中的调整
选择新建{date.date,adjustment}
).GroupBy(i=>i.Date).OrderBy(g=>g.Key);
在分组之前,您可以将所有日期的列表留给join adjustments,如下所示:
var adjustments = DAL.GetAdjustmentsInDateRange(Start, End);
// Get all unique dates in time span
IEnumerable<DateTime> dates = GetAllDates(Start, End);
var query = (from date in dates
join adjustment in adjustments
on date.Date equals adjustment.Created.Date into a
from adjustment in a.DefaultIfEmpty()
select new {date.Date, adjustment}
).GroupBy(i=>i.Date).OrderBy(g=>g.Key);
var adjustments=DAL.GetAdjustmentsInDateRange(开始、结束);
//获取时间跨度中的所有唯一日期
IEnumerable dates=GetAllDates(开始、结束);
变量查询=(日期中的起始日期)
在调整中加入调整
日期。日期等于调整。创建。日期
从a.DefaultIfEmpty()中的调整
选择新建{date.date,adjustment}
).GroupBy(i=>i.Date).OrderBy(g=>g.Key);
我已经组合了一个通用的LINQ到对象扩展方法,用于将缺少的内容插入到序列中:
public static IEnumerable<T> InsertMissing<T, U>(this IEnumerable<T> source,
Func<T, U> key, Func<U, U> increment, Func<U, T> create)
{
bool first = true;
U last = default(U);
foreach (var ig in source)
{
U current = key(ig);
if (first)
{
first = false;
last = current;
yield return ig;
continue;
}
while (!(last = increment(last)).Equals(current))
{
yield return create(last);
}
yield return ig;
}
}
然后,您需要在orderby
之后结束查询,然后进行此调用,然后将select
放在后面:
var allGroups = query.InsertMissing(
// Key selector
g => g.Key,
// Get next desired key from current key
d => d.AddDays(-1),
// Create item for missing key
d => new EmptyGrouping<DateTime,YourAdjustmentType>{ Key = d });
var allGroups=query.InsertMissing(
//键选择器
g=>g.键,
//从当前密钥中获取下一个所需密钥
d=>d.AddDays(-1),
//为缺少的密钥创建项
d=>newemptygroup{Key=d});
如果您的钥匙没有订购,或者其中一把钥匙没有落在正确的位置(例如,您的钥匙不是在午夜),这将导致混乱
这样做的优点是,不需要对原始源进行多次查询来确定最小/最大值,从而生成一个键列表,然后再进行一次查询来连接并获取数据。我已经提出了一种通用的LINQ to objects扩展方法,用于将缺失的内容插入到序列中:
public static IEnumerable<T> InsertMissing<T, U>(this IEnumerable<T> source,
Func<T, U> key, Func<U, U> increment, Func<U, T> create)
{
bool first = true;
U last = default(U);
foreach (var ig in source)
{
U current = key(ig);
if (first)
{
first = false;
last = current;
yield return ig;
continue;
}
while (!(last = increment(last)).Equals(current))
{
yield return create(last);
}
yield return ig;
}
}
然后,您需要在orderby
之后结束查询,然后进行此调用,然后将select
放在后面:
var allGroups = query.InsertMissing(
// Key selector
g => g.Key,
// Get next desired key from current key
d => d.AddDays(-1),
// Create item for missing key
d => new EmptyGrouping<DateTime,YourAdjustmentType>{ Key = d });
var allGroups=query.InsertMissing(
//键选择器
g=>g.键,
//从当前密钥中获取下一个所需密钥
d=>d.AddDays(-1),
//为缺少的密钥创建项
d=>newemptygroup{Key=d});
如果您的钥匙没有订购,或者其中一把钥匙没有落在正确的位置(例如,您的钥匙不是在午夜),这将导致混乱
这样做的好处是,不需要对原始源进行多次查询来确定最小/最大值,从而生成一个键列表,然后再进行一次查询来加入并获取数据。这看起来不错,但目前我在分组行上得到了一个错误,因为
调整
为null
(我离开了那条线,在同一条线下)。如果出现语法错误,很抱歉。请参阅Linq 101,左外联接是最后一个示例:我现在更新了答案,但group and order by使用的是方法语法,而不是查询语法。此解决方案对我有效,假设您可以先创建一个列表,列出开始
和结束
之间的所有日期,看起来不错,但在因为调整
为空
(我离开了那一行,在同一行下面),所以我在分组行上得到了一个错误。如果出现语法错误,很抱歉。请参阅Linq 101,左外连接是最后一个示例:我现在更新了答案,但group and order by使用的是方法语法,而不是查询语法。假设您可以首先创建开始
和结束
之间的所有日期的列表,此解决方案对我有效!我一定喜欢查询扩展ions,太好了!一定很喜欢查询扩展。