Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 创建包含缺少的键的分组_C#_Linq_Grouping - Fatal编程技术网

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,太好了!一定很喜欢查询扩展。