将列表排序为最佳解决方案?

时间:2013-03-01 10:25:42

标签: c# list sorting

我正在为学校做一个项目,我正在努力决定如何去做。

这是一个餐厅模拟。我生成一个表和等待方的随机列表。我随机预订了一些有预订的派对,而不是在等候名单上。我希望有保留的各方能够优先考虑。

是否对列表进行排序,以便所有有预订的方都在一端而另一方没有另一方是一个好的方法来解决这个问题?

然后我可以只是评估列表,看看该方是否适合在桌子上,然后坐下来或继续前进到下一方。或者有更聪明的方法吗?任何意见都赞赏!

5 个答案:

答案 0 :(得分:6)

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。选择标准需要适当扩展。如果此表中没有其他方位于此表中,则此表被评估为“正确”,但是如果人数计算的是相应表的席位数。如果找不到合适的表,则跳过该组。

答案 1 :(得分:3)

您可能希望使用Queue或类似构造的队列对餐馆进行建模,而不是使用List并采用不同的方法。这样,您将按照他们到达的顺序存储人员,因此无需进行排序。

将人员分组为Party对象。当缔约方到达时,您可以将它们添加到队列中。然后,您可以查看队列,如果某个方有预留,则将其从队列中删除并将其发送到他们的表中。如果该方没有预约,那么您检查一个表是否可用于该大小的一方,如果是,则从队列中删除该方。

否则,您可以等到表可用;当该事件发生时,您可以再次走队列,寻找符合表格大小的派对。您还可以检查队列此时是否包含具有预留的一方,这意味着他们优先考虑 - 使用Queue.First(x => x.HasReservation && x.Size <= Table.Places)从队列中获取有预订且可以适合的第一组人员表**。否则,Queue.First(x => x.Size <= Table.Places)将为您提供队列中适合该表的第一组人员。

使用队列的优点是不需要排序,您按照他们到达的顺序处理人员的各方,优先考虑有预订的人。

您在两点检查队列:

  1. 当人们到达时(他们有预订,是否有桌子)
  2. 当一个表可用时 - 首先查找队列中有预约并能够适应桌面的人;如果没有匹配,则从队列中取出与表大小匹配的第一组人(或者可以放在桌子上)
  3. 这是一个很好的起点。

    更新

    正如您所发现的,您无法从队列中间删除项目。这是因为队列是先进先出(FIFO)[而不是先进先出的堆栈 - LIFO]。为了避免排序,你可以使用像语句一样的列表 - 在this answer中有一个很好的例子。

    **这里有另一个有趣的排队问题 - 效率问题。如果有4个地方的桌子可用,你会怎么做?将它交给第一个到达桌面的派对,或者将它交给队列中适合桌面的最大派对。显然,第一种选择最适合客户服务,因为您坐的人等待时间最长,但第二种选择可以最大化您的利润,因为您可以更充分地利用表: - )

答案 2 :(得分:2)

如果您想对列表进行排序:

使用Enumerable.OrderByDescendingThenByDescending

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);
});

答案 3 :(得分:0)

在这种情况下,使用System.Linq可能是您排序列表的最佳选择。

类似的东西:

var sorted = tables.OrderByDescending(o => o.IsReserved);

答案 4 :(得分:0)

我只想使用两个队列(假设你的派对由一个名为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());
}