簡體   English   中英

Linq生成給定日期范圍的缺失記錄列表

[英]Linq produce a list of missing records for a given date range

假設我有以下類的列表:

public class Holding
{
  public string HoldingId{ get; set; }      
  public DateTime date { get; set; }
}

在給定的日期范圍內,每天需要持有一個持有者。 我需要能夠生成該范圍缺失的館藏列表。

所以說我有以下數據需要檢查2010年6月1日至2010年6月5日的范圍:

HoldingId Date
1         01-06-2010
1         02-06-2010
1         04-06-2010
2         02-06-2010
2         03-06-2010
2         05-06-2010
3         03-06-2010

對於這組數據,缺少的資產將是:

HoldingId Date
1         03-06-2010
1         05-06-2010   
2         01-06-2010
2         04-06-2010    
3         01-06-2010
3         02-06-2010
3         04-06-2010
3         05-06-2010

我使用以下問題的答案生成了日期列表范圍: 查找給定范圍的缺失日期

我不能完全理解如何從這里前進......我假設我需要通過HoldingId進行分組以生成一系列日期,然后執行range.Except(holdings.dates)或其他類似的效果。

有沒有人使用Linq有一個很好的解決這個問題的方法?

你應該怎么做才是對的; 這是我得到的;

List<Holding> holdings = new List<Holding>();
holdings.Add(new Holding(){ date=Convert.ToDateTime("01-06-2010"), HoldingId = "1" });
holdings.Add(new Holding(){ date=Convert.ToDateTime("02-06-2010"), HoldingId = "1" });
holdings.Add(new Holding(){ date=Convert.ToDateTime("04-06-2010"), HoldingId = "1" });
holdings.Add(new Holding(){ date=Convert.ToDateTime("02-06-2010"), HoldingId = "2" });
holdings.Add(new Holding(){ date=Convert.ToDateTime("03-06-2010"), HoldingId = "2" });
holdings.Add(new Holding(){ date=Convert.ToDateTime("05-06-2010"), HoldingId = "2" });
holdings.Add(new Holding(){ date=Convert.ToDateTime("03-06-2010"), HoldingId = "3" });

List<DateTime> dateRange = new List<DateTime>();
dateRange.Add(Convert.ToDateTime("01-06-2010"));
dateRange.Add(Convert.ToDateTime("02-06-2010"));
dateRange.Add(Convert.ToDateTime("03-06-2010"));
dateRange.Add(Convert.ToDateTime("04-06-2010"));
dateRange.Add(Convert.ToDateTime("05-06-2010"));

Dictionary<string, List<DateTime>> missingHoldings = new Dictionary<string, List<DateTime>>();

foreach(var holdGrp in  holdings.GroupBy (h => h.HoldingId))
{
    var missingDates = dateRange.Except(holdGrp.Select(h => h.date)).ToList();
    missingHoldings.Add(holdGrp.Key, missingDates);
}

另一種方法:

public static List<Holding> MissingHoldings(List<Holding> existingHoldings, DateTime startDate, DateTime endDate)
{
    var missingHoldings = new List<Holding>();
    var holdingIds = existingHoldings.Select(h => h.HoldingId).Distinct().ToList();
    var dates = new List<DateTime>();
    for (var current = startDate.Date; current <= endDate.Date; current = current.AddDays(1))
    {
        dates.Add(current);
    }

    foreach (var holdingId in holdingIds)
    {
        missingHoldings
            .AddRange(
                dates.Where(date => !existingHoldings.Any(h => h.HoldingId == holdingId && h.date == date))
                .Select(date => new Holding {HoldingId = holdingId, date = date}));
    }
    return missingHoldings;
}

一個純粹的Linq查詢受saj的回答啟發:

var missingHoldingsList =
 from h in holdings.GroupBy( h => h.HoldingId )
 from d in dateRange.Except( h.Select(x => x.date) ) 
 orderby h.Key, d
 select new Holding { date = d , HoldingId = h.Key };

saj的回答的無循環版本:

var missingHoldingsDict = (
  from h in holdings.GroupBy(h => h.HoldingId)
  select new
  {
    key = h.Key,
    holdings = 
      from d in dateRange.Except(h.Select(x => x.date))
      select new Holding { date = d, HoldingId = h.Key }
  }
).ToDictionary(
  h => h.key,
  h => h.holdings.ToList()
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM