我的IEnumerable<T>
字段有一个Created
字段,这是一个日期
每个日期可以有多个T
个,有时在给定日期没有T
个。
目前我按日期对这些内容进行分组,这样我就可以获得至少有一个T
和T
下的所有日期。
我想要的是,我可以将其用作查询的一部分,这将使我获得范围内的所有日期,无论是否存在具有给定日期的任何T
<。 / p>
当前代码:
var adjustments = DAL.GetAdjustmentsInDateRange(Start, End);
from adjustment in adjustments
group adjustment by adjustment.Created.Date into adjustmentsByDay
orderby adjustmentsByDay.Key descending
select ....
此处, adjustmentsByDay
的所有日期都不在Start
和End
之间。我想要的是它包含它们,没有元素。
我该怎么做?
答案 0 :(得分:2)
您可以在分组前将所有日期的列表保留为联接调整,如下所示:
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);
答案 1 :(得分:1)
我已经将一个通用的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;
}
}
您还需要IGrouping
的自定义实现:
class EmptyGrouping<K, E> : IGrouping<K, E> {
public K Key { get; set; }
public IEnumerator<E> GetEnumerator() {
return Enumerable.Empty<E>().GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator() {
return this.GetEnumerator();
}
}
然后,您需要在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 });
如果你的钥匙没有订购,或者如果其中一个没有落在正确的位置(例如在你的情况下,不是在午夜),这个会变得混乱。
这样做的好处是不需要对原始源进行多次查询来确定最小/最大值以生成密钥列表,然后再进一步查询以加入并获取数据。