【发布时间】:2019-04-30 10:17:43
【问题描述】:
我有两个插槽列表
public class Slot
{
public DateTime Start { get; set; }
public DateTime End { get; set; }
public List<Service> Services { get; set; }
}
public class Service
{
public int Id { get; set; }
public int Duration { get; set; }
}
public class MergingClass
{
public List<Slot> MergeSlots()
{
var mergedList = new List<Slot>();
var list1 = new List<Slot>
{
new Slot
{
Start = new DateTime(2018, 11, 1, 8, 0, 0),
End = new DateTime(2018, 11, 1, 11, 0, 0),
Services = new List<Service>
{
new Service
{
Duration = 20,
Id = 1
}
}
},
new Slot
{
Start = new DateTime(2018, 11, 1, 12, 0, 0),
End = new DateTime(2018, 11, 1, 16, 0, 0),
Services = new List<Service>
{
new Service
{
Duration = 20,
Id = 1
}
}
}
};
var list2 = new List<Slot>
{
new Slot
{
Start = new DateTime(2018, 11, 1, 8, 0, 0),
End = new DateTime(2018, 11, 1, 11, 0, 0),
Services = new List<Service>
{
new Service
{
Duration = 30,
Id = 2
}
}
},
new Slot
{
Start = new DateTime(2018, 11, 1, 12, 0, 0),
End = new DateTime(2018, 11, 1, 18, 0, 0),
Services = new List<Service>
{
new Service
{
Duration = 30,
Id = 2
}
}
}
};
return mergedList;
}
}
Start 和 End 是时间块,将除以服务持续时间(服务持续时间是 int 表示分钟)。
所以我有 2 个列表(用于 2 个不同的服务),我需要按开始和结束日期将它们合并到第三个列表(mergedList)中。
在这种情况下,方法 MergeSlots 应该返回:
mergedList = new List<Slot>
{
new Slot
{
Start = new DateTime(2018, 11, 1, 8, 0, 0),
End = new DateTime(2018, 11, 1, 11, 0, 0),
Services = new List<Service>
{
new Service
{
Duration = 20,
Id = 1
},
new Service
{
Duration = 30,
Id = 2
}
}
},
new Slot
{
Start = new DateTime(2018, 11, 1, 12, 0, 0),
End = new DateTime(2018, 11, 1, 16, 0, 0),
Services = new List<Service>
{
new Service
{
Duration = 20,
Id = 1
},
new Service
{
Duration = 30,
Id = 2
}
}
},
new Slot
{
Start = new DateTime(2018, 11, 1, 16, 0, 0),
End = new DateTime(2018, 11, 1, 18, 0, 0),
Services = new List<Service>
{
new Service
{
Duration = 30,
Id = 2
}
}
}
};
当然,这两个插槽列表都来自我无法影响的系统,并且每次都会有所不同。
我尝试一步一步做,但解决方案又大又丑,而且容易出错:
foreach (var slot in list2)
{
var slotWithStartInList1 = list1.FirstOrDefault(x => x.Start <= slot.Start && x.End > slot.Start);
if (slotWithStartInList1 != null)
{
if (slot.Start == slotWithStartInList1.Start)
{
if (slot.End == slotWithStartInList1.End)
{
slot.Services.AddRange(slotWithStartInList1.Services);
mergedList.Add(slot);
continue;
}
if (slot.End < slotWithStartInList1.End)
{
slot.Services.AddRange(slotWithStartInList1.Services);
slotWithStartInList1.Start = slot.End;
mergedList.Add(slot);
mergedList.Add(slotWithStartInList1);
continue;
}
slotWithStartInList1.Services.AddRange(slot.Services);
slot.Start = slotWithStartInList1.End;
mergedList.Add(slotWithStartInList1);
mergedList.Add(slot);
continue;
}
if (slot.End == slotWithStartInList1.End)
{
slotWithStartInList1.End = slot.Start;
slot.Services.AddRange(slotWithStartInList1.Services);
mergedList.Add(slotWithStartInList1);
mergedList.Add(slot);
continue;
}
if (slot.End > slotWithStartInList1.End)
{
var tempSlot = new Slot
{
Start = slot.Start,
End = slotWithStartInList1.End,
Services = new List<Services>()
};
tempSlot.Services.AddRange(slotWithStartInList1.Services);
tempSlot.Services.AddRange(slot.Services);
slotWithStartInList1.End = tempSlot.Start;
slot.Start = tempSlot.End;
mergedList.Add(tempSlot);
mergedList.Add(slot);
mergedList.Add(slotWithStartInList1);
continue;
}
var tempSlot2 = new Slot
{
Start = slotWithStartInList1.Start,
End = slot.Start,
Services = new List<Services>()
};
tempSlot2.Services.AddRange(slotWithStartInList1.Services);
slot.Services.AddRange(slotWithStartInList1.Services);
slotWithStartInList1.Start = slot.End;
mergedList.Add(tempSlot2);
mergedList.Add(slot);
mergedList.Add(slotWithStartInList1);
continue;
}
var slotWithEndInList1 = list1.FirstOrDefault(x => x.Start < slot.End && x.End >= slot.End);
if (slotWithEndInList1 != null)
{
if (slot.End == slotWithEndInList1.End)
{
slot.End = slotWithEndInList1.End;
slotWithEndInList1.Services.AddRange(slot.Services);
mergedList.Add(slot);
mergedList.Add(slotWithEndInList1);
continue;
}
var tempSlot2 = new Slot
{
Start = slotWithEndInList1.Start,
End = slot.End,
Services = new List<Services>()
};
tempSlot2.Services.AddRange(slotWithEndInList1.Services);
tempSlot2.Services.AddRange(slot.Services);
slot.End = tempSlot2.Start;
slotWithEndInList1.Start = tempSlot2.End;
mergedList.Add(tempSlot2);
mergedList.Add(slot);
mergedList.Add(slotWithEndInList1);
continue;
}
mergedList.Add(slot);
}
foreach (var slot in list1)
{
if (mergedList.Any(x => x.Start == slot.Start))
{
continue;
}
mergedList.Add(slot);
}
return mergedList;
我可以添加一些私有方法来避免代码重复,但我想知道是否有更好(更简洁、更短)的方法来实现我的目标?
也许一些 linq 扩展?
【问题讨论】:
-
由于您的程序有效,请考虑将其发布到codereview.stackexchange.com