代码之家  ›  专栏  ›  技术社区  ›  marr75

艰难的Linq查询

  •  1
  • marr75  · 技术社区  · 15 年前

    下面是最简单策略的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);
    

    我们现在有了具有相同优先级的行项目的“bucket”,在bucket中按到期日排序。我需要从每个桶中提取第一行项目,然后提取第二行项目,等等,直到我订购了所有项目。我想执行这个命令纯粹在linq。

    有人能想出一个方法来表达这一点完全在林?

    2 回复  |  直到 15 年前
        1
  •  4
  •   user7116    15 年前

    我不知道你怎么能把这个问题归结为一个比你现有的更好的问题,也许是nest 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;
    }
    

    编辑: 更新以匹配作者想要的段落。选择为每个优先级的第一个。

        2
  •  0
  •   Ian Mercer    15 年前

    LINQ=语言集成查询,而不是语言集成过程代码。

    如果您希望查询返回您需要将付款应用到的行项目,那么这是可以做到的(请参阅 .Aggregate foreach 循环是一个很好的构造。

    看到了吗 http://blogs.msdn.com/b/ericlippert/archive/2009/05/18/foreach-vs-foreach.aspx