买 X 支付 Y 算法
Buy X Pay for Y Algorithm
我要写"Buy X Pay for Y"算法。
到达我端点的请求是文章列表
public class Article
{
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
}
payFor 变量来自数据库,由包裹折扣 ID 定义
这是我到目前为止写的算法
if (purchasedQuantity >= minPurchaseQuantity)
{
var c = 0;
foreach (var article in articlesForPackage.OrderByDescending(a => a.UnitPrice))
{
for (var i = 1; i <= article.Quantity; i++)
{
c++;
if (c > payFor)
{
c = 0;
result.Add(new Discount
{
Value = article.UnitPrice
});
}
}
}
}
遗憾的是,此算法在某些情况下不起作用。
定义套餐折扣时买三付二有效,买三付一无效。
有人可以帮帮我吗?
算法应该是这样工作的:
我们有 3 篇文章
1 艺术 1 - 20$
2 艺术 2 - 30 美元
3 艺术 3 - 40$
如果 minPurchaseQuantity 为 3 且 payFor 为 2,则意味着 Art1 的成本应添加到结果列表中(因为它是最便宜的)
如果 minPurchaseQuantity 为 3 且 payFor 为 1,则表示应将 Art2 和 Art1 的成本添加到结果列表中(现在只有 Art2 添加)
好吧,主要问题是,当 c
大于 payFor
时,您会立即重置它。这在 minPurchaseQuantity-payFor=1
内有效,但在其他情况下无效。
虽然它不像我在第一个答案中提出的解决方案那么简单,但我认为实际算法可以更简洁地实现。以下代码首先对符合折扣条件的商品进行批处理。然后,对于每个批次,它会跳过多达 payFor
个项目,并计算其余
个项目的折扣
// first batch the items in batches eligible for discount (e.g. batches of three in take 3, pay for x)
var batchedItems = BatchItemsEligibleForDiscount(items, minPurchaseQuantity);
var discounts = batchedItems.Select(batch => batch.Skip(payFor))
.SelectMany(batch => batch) // flatten nested IEnumerable to an IEnumerable<Artible>
.Select(article => new Discount() { Value = article.UnitPrice });
BatchItemsEligibleForDiscount
获取符合折扣条件的批次(即如果 "take 3, pay for X" 则每批有 3 件商品。带有 [=22= 的文章] 是 "exploded",即如果数量为 3,则创建 3 个不同的对象。
IEnumerable<IEnumerable<Article>> BatchItemsEligibleForDiscount(items, minPurchaseQuantity)
{
return items.OrderByDescending(article => article.UnitPrice)
.Select(article => Enumerable.Range(1, article.Quantity).Select(n => new Article() { Quantity = 1, UnitPrice = article.UnitPrice })) // "explode" articles
.SelectMany(item => item) // flatten to an IEnumerable<Article>
.Select((article, index) => new { article, index })
.GroupBy(x => x.index / minPurchaseQuantity)
.Where(group => group.Count() == minPurchaseQuantity) // only take batches elegible for discount
.Select(group => group.Select(x => x.article));
}
请参阅 this fiddle 进行演示。
旧答案
计算折扣要容易得多。您可以计算符合折扣条件的捆绑包数量(如果需要 3 件,支付 2 件和 8 件商品,则您有两整包,每包 3 件)。通过计算拿取物品和支付物品之间的差额,乘以捆绑数量和每件物品的价格,可以计算出折扣
var numberOfDiscountableBundles = article.Quantity / amountOfItemsElegibleForDiscount;
var discount = numberOfDiscountableBundles * (amountOfItemsElegibleForDiscount - payFor) * article.UnitPrice;
例子:拍3件,买8件买1件:
numberOfDiscountableBundles = 8 / 3 = 2 (integer division!)
discount = 2 * (3 - 1) * p = 2 * 2 * p = 4 * p
这是两件打折的套装,每件三件(六件)。其中四件商品 未 付费(每捆仅一件),因此总价是一件商品价格的四倍折扣。
你可以将它封装在一个方法中
Discount CalculateDiscountForArticle(Article article, int amountOfItemsElegibleForDiscount, int payFor)
{
var numberOfDiscountableBundles = article.Quantity / amountOfItemsElegibleForDiscount;
var discount = numberOfDiscountableBundles * (amountOfItemsElegibleForDiscount - payFor) * article.UnitPrice;
return new Discount
{
Value = discount
};
}
并且您的原始函数变得和
一样简单
var discounts = articlesForPackage.OrderByDescending(a => a.UnitPrice)
.Select(a => CalculateDiscountForArticle(a, amountOfItemsElegibleForDiscount, payFor));
编辑旧答案
如果每个客户和文章仅授予一次折扣,则计算会有些不同
double discount = 0;
if(article.Quantity >= amountOfItemsElegibleForDiscount)
{
var discount = (amountOfItemsElegibleForDiscount - payFor) * article.UnitPrice;
}
我要写"Buy X Pay for Y"算法。 到达我端点的请求是文章列表
public class Article
{
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
}
payFor 变量来自数据库,由包裹折扣 ID 定义
这是我到目前为止写的算法
if (purchasedQuantity >= minPurchaseQuantity)
{
var c = 0;
foreach (var article in articlesForPackage.OrderByDescending(a => a.UnitPrice))
{
for (var i = 1; i <= article.Quantity; i++)
{
c++;
if (c > payFor)
{
c = 0;
result.Add(new Discount
{
Value = article.UnitPrice
});
}
}
}
}
遗憾的是,此算法在某些情况下不起作用。
定义套餐折扣时买三付二有效,买三付一无效。 有人可以帮帮我吗?
算法应该是这样工作的: 我们有 3 篇文章 1 艺术 1 - 20$ 2 艺术 2 - 30 美元 3 艺术 3 - 40$
如果 minPurchaseQuantity 为 3 且 payFor 为 2,则意味着 Art1 的成本应添加到结果列表中(因为它是最便宜的)
如果 minPurchaseQuantity 为 3 且 payFor 为 1,则表示应将 Art2 和 Art1 的成本添加到结果列表中(现在只有 Art2 添加)
好吧,主要问题是,当 c
大于 payFor
时,您会立即重置它。这在 minPurchaseQuantity-payFor=1
内有效,但在其他情况下无效。
虽然它不像我在第一个答案中提出的解决方案那么简单,但我认为实际算法可以更简洁地实现。以下代码首先对符合折扣条件的商品进行批处理。然后,对于每个批次,它会跳过多达 payFor
个项目,并计算其余
// first batch the items in batches eligible for discount (e.g. batches of three in take 3, pay for x)
var batchedItems = BatchItemsEligibleForDiscount(items, minPurchaseQuantity);
var discounts = batchedItems.Select(batch => batch.Skip(payFor))
.SelectMany(batch => batch) // flatten nested IEnumerable to an IEnumerable<Artible>
.Select(article => new Discount() { Value = article.UnitPrice });
BatchItemsEligibleForDiscount
获取符合折扣条件的批次(即如果 "take 3, pay for X" 则每批有 3 件商品。带有 [=22= 的文章] 是 "exploded",即如果数量为 3,则创建 3 个不同的对象。
IEnumerable<IEnumerable<Article>> BatchItemsEligibleForDiscount(items, minPurchaseQuantity)
{
return items.OrderByDescending(article => article.UnitPrice)
.Select(article => Enumerable.Range(1, article.Quantity).Select(n => new Article() { Quantity = 1, UnitPrice = article.UnitPrice })) // "explode" articles
.SelectMany(item => item) // flatten to an IEnumerable<Article>
.Select((article, index) => new { article, index })
.GroupBy(x => x.index / minPurchaseQuantity)
.Where(group => group.Count() == minPurchaseQuantity) // only take batches elegible for discount
.Select(group => group.Select(x => x.article));
}
请参阅 this fiddle 进行演示。
旧答案
计算折扣要容易得多。您可以计算符合折扣条件的捆绑包数量(如果需要 3 件,支付 2 件和 8 件商品,则您有两整包,每包 3 件)。通过计算拿取物品和支付物品之间的差额,乘以捆绑数量和每件物品的价格,可以计算出折扣
var numberOfDiscountableBundles = article.Quantity / amountOfItemsElegibleForDiscount;
var discount = numberOfDiscountableBundles * (amountOfItemsElegibleForDiscount - payFor) * article.UnitPrice;
例子:拍3件,买8件买1件:
numberOfDiscountableBundles = 8 / 3 = 2 (integer division!)
discount = 2 * (3 - 1) * p = 2 * 2 * p = 4 * p
这是两件打折的套装,每件三件(六件)。其中四件商品 未 付费(每捆仅一件),因此总价是一件商品价格的四倍折扣。
你可以将它封装在一个方法中
Discount CalculateDiscountForArticle(Article article, int amountOfItemsElegibleForDiscount, int payFor)
{
var numberOfDiscountableBundles = article.Quantity / amountOfItemsElegibleForDiscount;
var discount = numberOfDiscountableBundles * (amountOfItemsElegibleForDiscount - payFor) * article.UnitPrice;
return new Discount
{
Value = discount
};
}
并且您的原始函数变得和
一样简单var discounts = articlesForPackage.OrderByDescending(a => a.UnitPrice)
.Select(a => CalculateDiscountForArticle(a, amountOfItemsElegibleForDiscount, payFor));
编辑旧答案
如果每个客户和文章仅授予一次折扣,则计算会有些不同
double discount = 0;
if(article.Quantity >= amountOfItemsElegibleForDiscount)
{
var discount = (amountOfItemsElegibleForDiscount - payFor) * article.UnitPrice;
}