我正在为学校做一个项目,并试图决定我应该如何去做。
这是一个餐厅模拟。我生成一张桌子和等候方的随机列表。我随机安排了一些派对,有些派对没有在等候名单上。我希望有保留的各方拥有第一优先权。
是否对列表进行排序,以便所有有保留的各方都在一端,而没有另一端的一方是解决这个问题的好方法?
然后我可以评估列表,看看派对是否适合在桌子上,然后让他们入座或继续下一个派对。还是有更聪明的方法来解决这个问题?任何输入表示赞赏!
var groupedParties = parties.GroupBy(p => p.HasReservation);
这是迄今为止我看到的最干净的方式。你会得到一个包含两个组的列表,一个包含没有的缔约方,一个包含有保留的缔约方。您现在可以分别处理不同类型的等候派对的座位。
static void Main(string[] args)
{
GenerateRandomDataSomehow();
var groupedParties = _parties.GroupBy(p => p.HasReservation)
SeatParty(groupedParties.FirstOrDefault(g => g.Key == true));
SeatParty(groupedParties.FirstOrDefault(g => g.Key == false));
}
private static void SeatParty(IEnumerable<Party> partyGroup)
{
if (partyGroup == null) return;
foreach (var party in partyGroup.OrderBy(p => p.ArrivalTime))
{
var properTable = _tables.FirstOrDefault(t => t.SeatsCount == party.PersonsCount &&
t.Party == null);
if (properTable == null) continue;
properTable.Party = party;
}
}
这是一个带有更多 LINQ 的非常简单的实现。选择标准需要适当扩展。在此表中,如果没有其他方坐在此表上,则将其评估为“适当”,但如果人数准确,则相应表的座位数。如果找不到合适的表,则跳过该组。
您可能希望使用Queue或类似队列的构造而不是 List 来为您的餐厅建模,并采用不同的方法。这样,您将按照人员到达的顺序存储人员,因此无需进行排序。
将人员分组到一个 Party 对象中。当派对到达时,您可以将它们添加到队列中。然后,您可以查看队列,如果一方有预订,您可以将其从队列中删除并将其发送到他们的餐桌。如果该聚会没有预订,那么您检查是否有桌子可供该大小的聚会使用,如果有,则将该聚会从队列中移除。
否则,您可以等到 Table 可用;当该事件发生时,您可以再次排队,寻找适合餐桌大小的派对。您还可以在此时检查队列中是否包含有预订的派对,这意味着他们优先 - 用于Queue.First(x => x.HasReservation && x.Size <= Table.Places)
从队列中获取第一组有预订并且可以坐在桌子上的人**。否则,Queue.First(x => x.Size <= Table.Places)
将让您排在队列中的第一批适合坐在桌子旁的人。
使用队列的优点是不需要排序,您可以按照到达的顺序处理多人,优先考虑有预订的人。
您在两点检查队列:
这是一个很好的起点。
更新
正如您所发现的,您无法从队列中间移除项目。这是因为队列是先进先出 (FIFO) [与堆栈相反,堆栈是后进先出 - LIFO]。为了避免排序,您可以使用具有类似语义的队列的列表 -这个答案中有一个很好的例子。
** 这里还有另一个有趣的排队问题——效率问题。如果有 4 个位置的桌子可用,你会怎么做?把它给第一个到达的适合在桌子上的一方,或者给它在队列中适合在桌子上的最大的一方。显然,第一个选项最适合客户服务,因为您坐着等待时间最长的人,但第二个选项可以最大化您的利润,因为您可以更充分地利用桌子:-)
如果要对列表进行排序:
使用Enumerable.OrderByDescending
,ThenByDescending
var ordered = parties.OrderByDescending(p => p.HasReservation)
.ThenByDescending(p => p.PersonCount);
// if you want a new list use ordered.ToList()
foreach(var party in ordered)
{
// ...
}
如果要对原始列表进行排序,可以使用List<T>.Sort
自定义委托:
parties.Sort((p1, p2) =>
{
if (p1.HasReservation != p2.HasReservation)
return p1.HasReservation ? 1 : -1;
else
return p1.PersonCount.CompareTo(p2.PersonCount);
});
我会简单地使用两个队列(假设您的各方由一个名为Party
. 的类型表示。适当地更改类型):
Queue<Party> withReservation = new Queue<Party>();
Queue<Party> withoutReservation = new Queue<Party>();
您可以像这样将派对添加到队列中:
if (party has reservation) { // (condition in pseudo code)
withReservation.Enqueue(party);
} else {
withoutReservation.Enqueue(party);
}
你会坐在这样的派对上:
if (withReservation.Count > 0) {
Seat(withReservation.Dequeue());
} else if (withoutReservation.Count > 0) {
Seat(withoutReservation.Dequeue());
}
在这种情况下,使用System.Linq
可能是您对列表进行排序的最佳选择。
就像是:
var sorted = tables.OrderByDescending(o => o.IsReserved);