我有一个 C# 应用程序,我正在从跟踪人们请求的外部跟踪系统中提取数据,并将它们存储在我的数据库中。所以像这样:
public class Request
{
public DateTime Start {get;set;}
public DateTime End {get;set;}
public int PersonId {get;set;}
}
IEnumerable<Request> requests = GetExternalRequests();
GetExternalRequests() 的细节与问题无关。
问题是该服务将事情分解为每一天向我发送一个请求(即使该请求是多天的请求)
例如,如果一个人提出一个整周(周一到周五)的请求,我在数组中得到 5 个不同的项目(每个都有一个日期),我想将它们“合并”成一个请求开始 = 星期一和结束 = 星期五,以避免将 5 条不同的记录保存到我的数据库中。
到目前为止,我觉得这是一个非常不优雅的解决方案,我循环遍历所有请求并将结果放入字典中,然后运行下面的代码
IEnumerable<Request> requests = GetExternalRequests();
IEnumerable<Request> previousRequests = GetAllPreviousRequests();
Dictionary<string, Request> cachedDictionary = CacheAllRequestsByDateandPersonId(requests, previousRequests)
var groupedByPerson = requests.GroupBy(r=>r.PersonId);
foreach (var group in groupedByPerson)
{
foreach (Request request in group.OrderBy(r=>r.StartDate)
{
var offSet = 1;
if (request.StartDate.DayOfWeek == DayOfWeek.Friday)
{
offSet = 3;
}
if (cachedDictionary.ContainsKey(request.PersonId + request.StartDate.AddDays(offset))
{
//delete the request from the list and change the start date of the next request to the start date of this request.
}
}
}
所以我想得到一些建议,看看是否有更优雅的方式来“合并”这些结果。
增加一些清晰度(基于下面的一些评论)
- 请求不能重叠(想想休假请求)
- 如果我在周一已经收到了之前的请求,而在周二又收到了一个新请求,那么我也想合并这些请求
最佳答案
假设您的 GetExternalRequests 返回一些类似的种子数据
private static IEnumerable<Request> GetExternalRequests()
{
yield return new Request(new DateTime(2015, 1, 4), new DateTime(2015, 1, 4), 1);
yield return new Request(new DateTime(2015, 1, 5), new DateTime(2015, 1, 5), 1);
yield return new Request(new DateTime(2015, 1, 6), new DateTime(2015, 1, 6), 1);
yield return new Request(new DateTime(2015, 1, 7), new DateTime(2015, 1, 7), 1);
yield return new Request(new DateTime(2015, 1, 8), new DateTime(2015, 1, 8), 1);
yield return new Request(new DateTime(2015, 1, 11), new DateTime(2015, 1, 11), 1);
yield return new Request(new DateTime(2015, 1, 15), new DateTime(2015, 1, 15), 1);
yield return new Request(new DateTime(2015, 1, 19), new DateTime(2015, 1, 19), 1);
yield return new Request(new DateTime(2015, 1, 26), new DateTime(2015, 1, 26), 1);
yield return new Request(new DateTime(2015, 1, 4), new DateTime(2015, 1, 4), 2);
yield return new Request(new DateTime(2015, 1, 7), new DateTime(2015, 1, 7), 2);
}
然后你可以使用GroupBy合并你的数据,然后Aggregate合并连续的天数
请看下面的代码:
private static IList<Request> MergeRequests(IEnumerable<Request> requests)
{
return requests.GroupBy(r => r.PersonId)
.Aggregate(new Stack<Request>(), (list, grouping) =>
{
foreach (var request in grouping.OrderBy(r => r.StartDate))
{
var peek = list.Any() ? list.Peek() : null;
if (peek?.EndDate.Date.Day + 1 == request.StartDate.Date.Day)
peek.EndDate = request.EndDate;
else
list.Push(request);
}
return list;
})
.OrderBy(x => x.PersonId).ThenBy(x => x.StartDate)
.ToList();
}
那么让我们测试一下这个解决方案
public static void Main(string[] args)
{
Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("en-US");
IEnumerable<Request> requests = GetExternalRequests();
var requestsMerge = MergeRequests(requests);
foreach (var request in requestsMerge)
Console.WriteLine($"Person Id: {request.PersonId} - StartDate: {request.StartDate} - EndDate: {request.EndDate}");
}
输出数据是:
Person Id: 1 - StartDate: 1/4/2015 12:00:00 AM - EndDate: 1/8/2015 12:00:00 AM
Person Id: 1 - StartDate: 1/11/2015 12:00:00 AM - EndDate: 1/12/2015 12:00:00 AM
Person Id: 1 - StartDate: 1/19/2015 12:00:00 AM - EndDate: 1/19/2015 12:00:00 AM
Person Id: 1 - StartDate: 1/26/2015 12:00:00 AM - EndDate: 1/26/2015 12:00:00 AM
Person Id: 2 - StartDate: 1/4/2015 12:00:00 AM - EndDate: 1/4/2015 12:00:00 AM
Person Id: 2 - StartDate: 1/7/2015 12:00:00 AM - EndDate: 1/7/2015 12:00:00 AM
关于c# - 在 C# 中,将数组中的项合并为 "single larger item"的一部分的最优雅方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34601819/