【问题标题】:Linq With TakeWhile in C#在 C# 中使用 TakeWhile 的 Linq
【发布时间】:2016-10-05 19:42:19
【问题描述】:

获取最佳卡片列表的最佳方法是什么,例如,我想获得礼品卡以申请订单总数为 100。它应该返回最佳组合,例如 30+40+75。下面是我当前的代码,它在30+40 = 70 之后停止,这是错误的,因为订单总数超过 70,所以我们不能只申请两张礼品卡。如上所示,它应该返回 3 张礼品卡。

[Test]
public void GetBestAvailableGiftCards()
{
    var list = new List<GiftCard>
    {
        new GiftCard() {CardNumber = "45964123358448514", SecurityCode = "032443", Balance = 75},
        new GiftCard() {CardNumber = "45964123345954414", SecurityCode = "032443", Balance = 85},
        new GiftCard() {CardNumber = "45964062845645735", SecurityCode = "435448", Balance = 40},
        new GiftCard() {CardNumber = "28872034245533173", SecurityCode = "934465", Balance = 30}
    };

    var orderTotal = 100;
    double current = 0;
    var cards = list
        .OrderBy(x => x.Balance)
        .TakeWhile(card => (current = current + card.Balance) <= orderTotal)
        .ToList();
}

【问题讨论】:

  • 你的代码有什么问题?它会给你不正确的结果吗?你期望什么输出?
  • 它停在那里,因为下一个结果是30+40+75,它大于 100(这是您的检查结果)。
  • 为什么正确的结果是3张牌? 30+40+75 = 145,大于 100。
  • 30+40+75
  • 您要解决的问题称为 Knapsack problem(更具体地说是 Subset sum problem)。我建议您在尝试半心半意的解决方案之前先阅读一下。

标签: c# entity-framework linq c#-4.0


【解决方案1】:

这是TakeWhile 的通常行为,只要指定条件为真,它就会从序列中返回元素。

你必须调整这有点包含下一个添加(这使得条件为真)。

    var orderTotal = 100;
    double current = 0;
    var cards = list
        .OrderBy(x => x.Balance)
        .TakeWhile(card => 
         {              
            bool returnvalue = current < orderTotal; 
            current += card.Balance;
            return returnvalue;
        })
        .ToList();

检查这个example

【讨论】:

  • 它必须是bool returnvalue = current &lt; orderTotal; 而不是&lt;=
【解决方案2】:

如果我的问题没有错,您正在尝试选择礼品卡的某些子集,以使其余额总和尽可能接近orderTotal,小于或等于orderTotal。在给定的情况下,最好的选择是只给用户 85 卡,因为在我看来没有其他组合更好。

遗憾的是,这不能简单地通过直接使用 LINQ 来解决。如果这不是 NP 难题,请尝试使用一些动态算法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-04-27
    • 2019-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-07
    相关资源
    最近更新 更多