Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/79.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#_Sql - Fatal编程技术网

C#-将具有日期的行分组为具有时间持续时间的块

C#-将具有日期的行分组为具有时间持续时间的块,c#,sql,C#,Sql,这有点难以解释。我有一个包含计划信息的数据表。每行代表一个带有开始日期/时间和结束日期/时间的计划。我需要对这些进行分组,以便总体开始到结束时间与给定的持续时间相匹配 例如,我的数据表中可能有以下内容: Schedule1: Start - 9:00AM, End - 9:30AM Schedule2: Start - 9:30AM, End - 10:00AM Schedule3: Start - 10:00AM, End - 10:30AM Schedule4: Start - 10:30A

这有点难以解释。我有一个包含计划信息的数据表。每行代表一个带有开始日期/时间和结束日期/时间的计划。我需要对这些进行分组,以便总体开始到结束时间与给定的持续时间相匹配

例如,我的数据表中可能有以下内容:

Schedule1: Start - 9:00AM, End - 9:30AM
Schedule2: Start - 9:30AM, End - 10:00AM
Schedule3: Start - 10:00AM, End - 10:30AM
Schedule4: Start - 10:30AM, End - 11:00AM
现在,如果给我一个持续时间值60分钟,那么我需要能够生成以下输出:

Block1: Schedules(1,2): 9:00AM - 10:00AM
Block2: Schedules(2,3): 9:30AM - 10:30AM
Block3: Schedules(3,4): 10:00AM - 11:00AM
但是,如果持续时间改为120分钟,则我需要生成以下内容:

Block1: Schedules(1,2,3,4): 9:00AM - 11:00AM

如果需要澄清,请告诉我。我需要用C语言编写一个方法来进行转换。请帮我解决这个问题,因为我已经花了很长时间在这个问题上。

您选择用C#还是SQL来解决这个问题部分取决于数据的规模。假设我们使用的时间范围相对较少(比如<10),那么将所有时间都拉入内存并在C#中查找块是合理的

鉴于以下类别:

public class Schedule {
    public int ID { get; set; }
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
    public int Minutes { get; set; }
}

public class ScheduleBlock : Schedule {
    public List<Schedule> Schedules { get; set; }
}

为什么您需要在C#中执行此操作,而不是编写SQL查询来获取结果?要扩展SpaceghostAli的观点,您是否使用实体框架来执行此查询?如果你使用的是ADO,那么它将是直接的SQL。我想我可以用SQL来实现……我只是觉得用c#更简单。如果你有一个sql的解决方案,我也可以使用它。如果你要花那么多的精力去寻找答案,至少要让它变得优雅。尝试使用递归和PLinq之类的工具。@Tsabo:请随意提供一个替代解决方案。这是我的午餐时间练习:我确实考虑过递归,但我想不出一个好的算法。使用PLinq可能会使代码稍微更有效率,但不会改变算法。例如,为ScheduleBlock提供对所有可用计划的引用,并使用递归方法查找所有可能的延续。每个步骤都会出现深度克隆ScheduleBlock,这是一个潜在的结果。使用PLinq在所有时间表上启动该方法。@mellamokb-非常感谢您抽出时间回答我的问题。你的解决方案对我真的很有帮助。不管它是不是递归,任何有效的方法都可以。如果我有任何问题或者有什么我不明白的,我会回复你。
public List<ScheduleBlock> CombineAllSchedules(List<Schedule> origschedules, out int added)
{
    added = 0;
    var schedules = new List<ScheduleBlock>();
    foreach (var s in origschedules) {
        var snew = new ScheduleBlock { Schedules = new List<Schedule> { s }, Start = s.Start, End = s.End, Minutes = s.Minutes };
        schedules.Add(snew);
    }

    for (var i = 0; i < schedules.Count; i++) {
        var s = schedules[i];
        var matchstart = schedules.Where (s2 => s2.End == s.Start).ToList();
        var matchend = schedules.Where (s2 => s2.Start == s.End).ToList();
        foreach (var s2 in matchstart) {
            var newschedule = CombineSchedules(s2, s);
            if (!schedules.Any (sc => sc.Start == newschedule.Start && sc.End == newschedule.End)) {
                schedules.Add(newschedule);
                added++;
            }
        }

        foreach (var s2 in matchend) {
            var newschedule = CombineSchedules(s, s2);
            if (!schedules.Any (sc => sc.Start == newschedule.Start && sc.End == newschedule.End)) {
                schedules.Add(newschedule);
                added++;
            }
        }
    }
    return schedules;
}

public ScheduleBlock CombineSchedules(Schedule s1, Schedule s2)
{
    var schedules = new List<Schedule>();
    if (s1 is ScheduleBlock) schedules.AddRange(((ScheduleBlock)s1).Schedules);
    else schedules.Add(s1);
    if (s2 is ScheduleBlock) schedules.AddRange(((ScheduleBlock)s2).Schedules);
    else schedules.Add(s2);
    var s = new ScheduleBlock {
        Schedules = schedules,
        Start = s1.Start, End = s2.End, Minutes = s1.Minutes + s2.Minutes
    };
    return s;
}
public List<ScheduleBlock> FindBlocks(List<Schedule> schedules, int blockLength)
{
    int added;
    var combinedSchedules = CombineAllSchedules(schedules, out added);
    var result = combinedSchedules.Where (s => s.Minutes == blockLength).ToList();
    return result;
}
var schedules = new List<Schedule> {
    new Schedule { ID = 1, Start = DateTime.Parse("09:00 AM"), End = DateTime.Parse("09:30 AM") },
    new Schedule { ID = 2, Start = DateTime.Parse("09:30 AM"), End = DateTime.Parse("10:00 AM") },
    new Schedule { ID = 3, Start = DateTime.Parse("10:00 AM"), End = DateTime.Parse("10:30 AM") },
    new Schedule { ID = 4, Start = DateTime.Parse("10:30 AM"), End = DateTime.Parse("11:00 AM") },
};

foreach (var s in schedules) {
    s.Minutes = (int)(s.End - s.Start).TotalMinutes;
}

Console.WriteLine("60 Minute Blocks");
Console.WriteLine("----------------");
var blocks = FindBlocks(schedules, 60);
var blockId = 1;
foreach (var block in blocks) {
    var output = "Block" + blockId + 
        ": Schedules(" + string.Join(",", block.Schedules.Select (s => s.ID)) + "): " +
        block.Start.ToString("h:mmtt") + " - " + block.End.ToString("h:mmtt");
    Console.WriteLine(output);
    blockId++;
}

Console.WriteLine();
Console.WriteLine("120 Minute Blocks");
Console.WriteLine("----------------");
blocks = FindBlocks(schedules, 120);
blockId = 1;
foreach (var block in blocks) {
    var output = "Block" + blockId + 
        ": Schedules(" + string.Join(",", block.Schedules.Select (s => s.ID)) + "): " +
        block.Start.ToString("h:mmtt") + " - " + block.End.ToString("h:mmtt");
    Console.WriteLine(output);
    blockId++;
}
60 Minute Blocks
----------------
Block1: Schedules(1,2): 9:00AM - 10:00AM
Block2: Schedules(2,3): 9:30AM - 10:30AM
Block3: Schedules(3,4): 10:00AM - 11:00AM

120 Minute Blocks
----------------
Block1: Schedules(1,2,3,4): 9:00AM - 11:00AM