【问题标题】:Slice array into sub-arrays of varying sizes (C#)将数组分割成不同大小的子数组(C#)
【发布时间】:2022-11-10 17:51:13
【问题描述】:

在编写代码 Kata 时,我遇到了一个轻微的逻辑问题,我无法找到解决方案。这不是完成任务的硬性要求,但它让我对如何处理它很感兴趣。

Kata 正在通过一系列定价规则模拟应用定价折扣和超市结账 (see full Kata here)。为了玩转一些继承和接口功能,我添加了“买 X 送 Y”的规则。当有问题的Y1 时它工作正常,但在那之后开始变得有点朦胧......

例如,我尝试了“购买3,免费获得2”的想法。我尝试通过将物品分组为 5 个一组,并通过减去其中两个物品的价格来计算每组的折扣:

    public override double CalculateDiscount(Item[] items)
    {
        //per the example described above
        //_groupSize = 5, _buy = 3
        //meaning 2 out of every group of 5 items should be free

        var discountGroups = new List<IEnumerable<Item>>();

        for (var i = 0; i < items.Length / _groupSize; i++)
        {
            discountGroups.Add(items.Skip(i * _groupSize).Take(_groupSize));
        }

        return discountGroups
            .Sum(group => group
                .Skip(_buy)
                .Sum(item => item.Price)
            );
    }

我发现上面的代码按预期工作(如果每个项目都有1.00Price 属性,则上面将返回2.00)。我希望解决的一个极端情况是,在添加第五个项目之前它不会生效(因此,您为每个项目做广告时的价格将变为 1.002.003.004.003.00)。

我最理想的情况是,一旦你的收藏中有三件物品,接下来的两件是免费的,无论你选择只拿一件还是两件都不应该影响价格。我知道这对领域来说不是很现实,但我有兴趣尝试将其作为技术问题来解决。

我有一些裂缝,但没有成功地比上面的代码更接近。我认为我需要做的是将数组分组为所需的最少购买物品数量,然后是可变数量的免费物品。我可能可以硬编码一些东西来解决这个问题,但是如果我要模拟购买 3 件商品并免费获得 2 件商品,然后购买 3 件商品但只拿一件免费商品,这会变得复杂。

任何有关如何解决此问题的建议将不胜感激!

谢谢, 标记

【问题讨论】:

  • 真的不太现实,因为您的商品可能有不同的价格,这意味着目前客户必须支付的价格是运气。
  • @TimSchmelter我应该澄清一下,这是在过滤项目以检查它们是否都属于同一类型之后,因此没有风险。正如我所说,这更多的是我从数组操作的角度感兴趣,而不是试图对超市的领域规则进行严格建模。

标签: c# arrays linq slice


【解决方案1】:

您的跳过...采取方法是错误的。如果你想使用 LINQ,你可以使用GroupBy,其中 group-key 是 item-index 和 group-size(5) 的整数除法结果:

public class DiscountCalculator
{
    public DiscountCalculator(int discountMinCount, int freeCount)
    {
        DiscountMinCount = discountMinCount;
        FreeCount = freeCount;
    }

    public int DiscountMinCount { get; set; }
    public int FreeCount { get; set; }


    // What I would ideally like is that, once you have three items in your collection,
    // the next two items are free, whether you choose to take just one or two of them shouldn't affect the price
    public decimal CalculatePrice(Item[] items)
    {
        if (items.Length < DiscountMinCount) return items.Sum(item => item.Price);
        int groupSize = DiscountMinCount + FreeCount;

        return items.Select((i, ix) => (Item: i, Index: ix))
            .GroupBy(x => x.Index / groupSize)
            .Select(g => g.Select((x, ix) => (Item: x.Item, NumberInGroup: ix + 1))
                .Sum(x => x.NumberInGroup > DiscountMinCount ? 0 : x.Item.Price))
            .Sum();
    }
}

一个样品:

DiscountCalculator dc = new DiscountCalculator(3, 2);
Item item = new Item { Price = 1 };
Item[] items = { item , item , item , item, item, item, item, item };
Console.WriteLine(dc.CalculatePrice(items));

结果是 6

  • 8 件,每件价格=1
  • 第 4 项和第 5 项是免费的
  • 如果我再添加 1 或 2 件商品,价格将保持不变

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多