不足しているものをシーケンスに挿入するために、汎用の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 });
キーが注文されていない場合、またはキーの1つが正しい場所にない場合(たとえば、真夜中にない場合)、これは問題になります。
これには、キーのリストを生成するために最小/最大値を決定するために元のソースで複数のクエリを実行する必要がなく、データを結合して取得するためにさらにクエリを実行する必要がないという利点があります。