【问题标题】:How to avoid writing three loops in this example?在这个例子中如何避免写三个循环?
【发布时间】:2016-09-20 06:34:18
【问题描述】:

在下面的代码示例中,如何避免编写 3 个循环。我不确定如何保持代码可读性并仍然对其进行优化。这不是我正在处理的确切功能,但为简洁起见,我对其进行了更新,供大家阅读。

int OrderQuantity = 5;
List<LineItem> Items = GetLineItems();
List<int> UniqueOrderIDs = new List<int>();

foreach (LineItem i in Items) {
    if (UniqueOrderIDs.Contains(i.OrderID) == false) {
        PurchaseOrder Order = GetOrder(i.OrderId);
        Order.ModifiedDate = Now;
        UpdateOrder(Order);
        UniqueOrderIDs.Add(i.OrderID);
    }
}

foreach (int id in UniqueOrderIDs) {
    decimal TaxableAmount = 0;

    foreach (LineItem i in Items) {
        If(i.OrderID == id){
            i.OrderQuantity = OrderQuantity;
            UpdateItem(i)

            TaxableAmount += i.Cost;
        }
    }

    UpdateTaxAmount(id, TaxableAmount);
}

【问题讨论】:

  • 我认为你只需要一个按 LineItemId 的组,然后你就只有一个循环。
  • LineItemID 在这里已经是唯一的。 OrderID 不是唯一的。
  • 我不明白为什么这个问题被否决了。
  • 所以你有问题。 GetLineItems(OrderID),如果你传递 OrderID,为什么它返回不同的 OrderID?它应该只过滤您传递的 OrderID。
  • 很抱歉你是对的。我获得多个订单的订单项。我在写问题时有一个错字。

标签: c# loops optimization


【解决方案1】:

你可以这样做(我在这里省略了边界检查)

List<LineItem> items = GetLineItems(OrderID);
var sorted = items.OrderBy(i=>i.OrderID);

int id = sorted.First().OrderID; //get 1st element's id

foreach (LineItem i in sorted.Skip(1)) //skip 1st one
{
    if(i.OrderID == id)
    {
        i.OrderQuantity = OrderQuantity;
        UpdateItem(i)    
        TaxableAmount += i.Cost;            
    }
    else 
       id = i.OrderID;
}

....

在简单地迭代它之后,您可以按OrderIDLineItem 列表进行排序,虽然它是相同的,但您可以做任何您需要做的事情。

可能会有人选择LINQ 解决方案,但在我看来,这看起来更简单明了,然后LINQ 解决方案可能就是在这种情况下。

【讨论】:

  • 所以在其他部分我会调用 UpdateTaxAmount 并重置税额,对吗?如果是的话,我考虑过这个解决方案,但这真的很难阅读。我在循环中做了很多事情,所以必须真正注意看看循环内部发生了什么。因此我选择了第三个循环...
  • @user3587180: 对,else 处理 ID 不相等的情况(假设每个 ID 发生一次)
  • @user3587180:把“很多东西”分成函数调用,重新架构它,这样阅读起来更简单。
  • 好的,我同意你的回答。但是,我认为 if 应该检查 orderid id 是否然后更新税额。不应该有任何其他内容,默认值是更新项目和增值税金额。如果您愿意,可以更新您的答案...感谢您的帮助!
  • 虽然我应该提一下,如果我添加了有界检查,这种方法读起来就不好看...
【解决方案2】:

我可能遗漏了一些东西(在这里迟到了),但你为什么不能这样做:

var orderIdAndTaxableAmount = new Dictionary<int, decimal>();

foreach (LineItem i in Items) {
    if (UniqueOrderIDs.Contains(i.OrderID) == false) {
        PurchaseOrder Order = GetOrder(i.OrderId);
        Order.ModifiedDate = Now;
        UpdateOrder(Order);
        UniqueOrderIDs.Add(i.OrderID);
    }

    i.OrderQuantity = OrderQuantity;
    UpdateItem(i);

    if (!orderIdAndTaxableAmount.ContainsKey(i.OrderId))
    {
        orderIdAndTaxableAmount.Add(i.OrderId, 0.0);
    }
    orderIdAndTaxableAmount[i.OrderId] += i.Cost;
}

foreach (var kvp in orderIdAndTaxableAmount)
{
    UpdateTaxAmount(kvp.Key, kvp.Value);
}

【讨论】:

  • 那行得通,但我正在研究的方法非常大。它有很多检查,因此以这种方式实现会使阅读变得更加困难。理想情况下,我会以您的方式或@Tigran 方式实现它..
  • 然后我会尝试重构一些部分以拥有自己的方法。例如SetModifiedDateForPurchaseOrder(i.OrderId);UpdateOrderQuantity(i);。当然,在给定的示例中它有点过分,但如果你的方法很大,我猜至少有一些东西可以重构为自己的方法,从而使其更具可读性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-29
相关资源
最近更新 更多