Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中,合并数组中的项的最优雅方式是什么;单个较大的项目;?_C#_Collections_Merge - Fatal编程技术网

C# 在C中,合并数组中的项的最优雅方式是什么;单个较大的项目;?

C# 在C中,合并数组中的项的最优雅方式是什么;单个较大的项目;?,c#,collections,merge,C#,Collections,Merge,我有一个C#应用程序,我从一个外部跟踪系统中提取数据,跟踪人们的请求,并将其存储在我的数据库中。比如说: public class Request { public DateTime Start {get;set;} public DateTime End {get;set;} public int PersonId {get;set;} } IEnumerable<Request> requests = GetExternalRequests(); publ

我有一个C#应用程序,我从一个外部跟踪系统中提取数据,跟踪人们的请求,并将其存储在我的数据库中。比如说:

public class Request
{
   public DateTime Start {get;set;}
   public DateTime End {get;set;}
   public int PersonId {get;set;}
} 

IEnumerable<Request> requests = GetExternalRequests();
public class Request
{
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
    public int PersonId { get; set; }
    public Request(DateTime start)
    {
        while (!IsWorkingDay(start))
            start = start.AddDays(1);
        Start = start;

        End = start.AddDays(1);
        while (!IsWorkingDay(End))
            End = End.AddDays(1);
    }

    private bool IsWorkingDay(DateTime date)
    {
        return date.DayOfWeek != DayOfWeek.Saturday && date.DayOfWeek != DayOfWeek.Sunday;
    }

    public bool Intersects(Request otherRequest)
    {
        if (otherRequest == this)
            return true;

        return !(otherRequest.End < Start || otherRequest.Start > End);
    }

    public void Merge(Request otherRequest)
    {
        if (otherRequest.Start < Start)
            Start = otherRequest.Start;
        if (otherRequest.End > End)
            End = otherRequest.End;
    }
}
公共类请求
{
公共日期时间开始{get;set;}
公共日期时间结束{get;set;}
公共int PersonId{get;set;}
} 
IEnumerable 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.
         }
    }
}
IEnumerable requests=GetExternalRequests();
IEnumerable previousRequests=GetAllPreviousRequests();
Dictionary cachedDictionary=CacheAllRequestsByDate和PersonId(请求,以前的请求)
var groupedByPerson=requests.GroupBy(r=>r.PersonId);
foreach(groupedByPerson中的var组)
{
foreach(请求位于group.OrderBy(r=>r.StartDate)中)
{
var偏移=1;
if(request.StartDate.DayOfWeek==DayOfWeek.Friday)
{
偏移量=3;
}
if(cachedDictionary.ContainsKey(request.PersonId+request.StartDate.AddDays(offset))
{
//从列表中删除请求,并将下一个请求的开始日期更改为此请求的开始日期。
}
}
}
所以我想得到一些建议,看看是否有更优雅的方式来“合并”这些结果

增加一些清晰度(基于下面的一些评论)

  • 请求不能重叠(请考虑假期请求)
  • 如果我周一已经有一个以前的请求,而周二又有一个新的请求,那么我也想合并这些请求

假设您的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);
}
private静态IEnumerable GetExternalRequests()
{
生成返回新请求(新日期时间(2015,1,4),新日期时间(2015,1,4),1);
生成返回新请求(新日期时间(2015,1,5),新日期时间(2015,1,5),1);
生成返回新请求(新日期时间(2015,1,6),新日期时间(2015,1,6),1);
生成返回新请求(新日期时间(2015,1,7),新日期时间(2015,1,7),1);
生成返回新请求(新日期时间(2015,1,8),新日期时间(2015,1,8),1);
生成返回新请求(新日期时间(2015,1,11),新日期时间(2015,1,11),1);
生成返回新请求(新日期时间(2015,1,15),新日期时间(2015,1,15),1);
生成返回新请求(新日期时间(2015,1,19),新日期时间(2015,1,19),1);
生成返回新请求(新日期时间(2015,1,26),新日期时间(2015,1,26),1);
生成返回新请求(新日期时间(2015,1,4),新日期时间(2015,1,4),2);
生成返回新请求(新日期时间(2015,1,7),新日期时间(2015,1,7),2);
}
然后,您可以使用GroupBy合并数据,然后聚合以合并连续的天数

请参阅下面的代码:

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();
}
私有静态IList合并请求(IEnumerable请求)
{
return requests.GroupBy(r=>r.PersonId)
.Aggregate(新堆栈(),(列表,分组)=>
{
foreach(grouping.OrderBy(r=>r.StartDate)中的var请求)
{
var peek=list.Any()?list.peek():null;
if(peek?.EndDate.Date.Day+1==request.StartDate.Date.Day)
peek.EndDate=request.EndDate;
其他的
列表、推送(请求);
}
退货清单;
})
.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}");
}
publicstaticvoidmain(字符串[]args)
{
Thread.CurrentThread.CurrentCulture=CultureInfo.GetCultureInfo(“en-US”);
IEnumerable requests=GetExternalRequests();
var requestsMerge=合并请求(请求);
foreach(requestsMerge中的var请求)
WriteLine($“个人Id:{request.PersonId}-StartDate:{request.StartDate}-EndDate:{request.EndDate}”);
}
输出数据如下:

人员Id:1-开始日期:2015年4月1日12:00:00-结束日期:2015年8月1日12:00:00

人员Id:1-开始日期:2015年11月1日12:00:00-结束日期:2015年12月1日12:00:00

人员Id:1-开始日期:2015年1月19日12:00:00-结束日期:2015年1月19日12:00:00

个人Id:1-开始日期:2015年1月26日12:00:00-结束日期:2015年1月26日12:00:00

人员Id:2-开始日期:2015年1月4日12:00:00-结束日期:2015年1月4日12:00:00

人员Id:2-开始日期:2015年7月1日12:00:00-结束日期:2015年7月1日12:00:00


cachedDictionary.Contains
字典上
是一种linq方法,它使用蛮力搜索。这肯定是算法中最慢的部分


我建议更改内部循环的内容。不要尝试修改请求。相反,请创建一个新的请求列表,仅当内部循环中遇到非连续的一天时才创建一个新请求。请求的结束将在下一个请求启动或循环完成时设置。

您可以尝试som就像这样:

public class Request
{
   public DateTime Start {get;set;}
   public DateTime End {get;set;}
   public int PersonId {get;set;}
} 

IEnumerable<Request> requests = GetExternalRequests();
public class Request
{
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
    public int PersonId { get; set; }
    public Request(DateTime start)
    {
        while (!IsWorkingDay(start))
            start = start.AddDays(1);
        Start = start;

        End = start.AddDays(1);
        while (!IsWorkingDay(End))
            End = End.AddDays(1);
    }

    private bool IsWorkingDay(DateTime date)
    {
        return date.DayOfWeek != DayOfWeek.Saturday && date.DayOfWeek != DayOfWeek.Sunday;
    }

    public bool Intersects(Request otherRequest)
    {
        if (otherRequest == this)
            return true;

        return !(otherRequest.End < Start || otherRequest.Start > End);
    }

    public void Merge(Request otherRequest)
    {
        if (otherRequest.Start < Start)
            Start = otherRequest.Start;
        if (otherRequest.End > End)
            End = otherRequest.End;
    }
}
公共类请求
{
公共日期时间开始{get;set;}
公共日期时间结束{get;set;}
公共int PersonId{get;set;}