说我有以下课程的列表:
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
我使用以下问题的答案生成了日期列表范围: Find missing dates for a given range。
我不能完全理解如何从这里前进......我假设我需要通过HoldingId分组来生成一系列日期然后做range.Except(holdings.dates)或者其他什么为此。
使用Linq有没有人能很好地解决这个问题?
答案 0 :(得分:2)
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);
}
答案 1 :(得分:1)
另一种方法:
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;
}
答案 2 :(得分:1)
纯粹的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()
);