我有一份IEnumerable发票,这些发票都有订单项。这些订单项具有优先权。我正在编写各种策略来自动应用这些订单项的现金,其中一个给我带来了一些麻烦。我的模式是准备一个linq语句来订购发票的订单项,然后按顺序迭代linq查询,直到我用完为止。
最简单策略的linq语句示例,按优先级和截止日期支付每个项目,如下所示:
from lineItem in invoices.SelectMany(invoice => invoice.LineItems)
orderby lineItem.Priority, lineItem.DueDate
select lineItem;
其中一个策略是按优先顺序将现金应用于具有给定优先级的最旧的剩余项目,然后移至每个优先级的下一个最早的项目。
编辑:如何启动我要求的查询的示例 -
from lineItem in invoices.SelectMany(invoice => invoice.LineItems)
group lineItem by lineItem.Priority into priorities
orderby priorities.Key
select priorities.OrderBy(item => item.DueDate);
我们现在拥有具有相同优先级的订单项“存储桶”,按存储桶中的截止日期排序。我需要从每个桶中提取第一个行项目,然后是第二个行等,直到我订购了所有项目。我想纯粹在linq中执行这个排序。
有人能想出一种在linq中完全表达这种方式的方法吗?
答案 0 :(得分:4)
我不知道如何将这个问题提供给比您拥有的更好的查询,可能会嵌套from
个查询以自动执行SelectMany
。
var proposedPayments = new List<LineItem>();
decimal cashOnHand = ...;
var query = invoices.SelectMany(iv => iv.LineItems)
.GroupBy(li => li.Priority)
.SelectMany(gg =>
gg.OrderBy(li => li.DueDate)
.Select((li,idx) => Tuple.Create(idx, gg.Key, li)))
.OrderBy(tt => tt.Item1)
.ThenBy(tt => tt.Item2)
.Select(tt => tt.Item3);
foreach (var item in query)
{
if (cashOnHand >= item.Cost)
{
proposedPayments.Add(item);
cashOnHand -= item.Cost;
}
if (cashOnHand == 0m) break;
}
更新修改以匹配作者想要的段落。被选为每个优先级的第一个。
答案 1 :(得分:0)
LINQ =语言集成查询而非语言集成程序代码。
如果您想要一个返回您需要应用付款的订单项的查询,那么这是可行的(请参阅.Aggregate
),但如果您想实际将资金应用于订单项,那么go,然后foreach
循环是一个很好用的构造。
请参阅http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx