Code Trivia:优化多个嵌套循环的代码

时间:2010-03-26 16:43:28

标签: .net performance

我今天遇到了这个代码,并想知道我们可以通过哪些方式对其进行优化。

显然,该模型很难改变,因为它是遗产,但有兴趣获得意见。

更改了一些名称并模糊了一些核心逻辑以保护。

private static Payment FindPayment(Order order, Customer customer, int paymentId)
    {
        Payment payment = Order.Payments.FindById(paymentId);
        if (payment != null)
        {
            if (payment.RefundPayment == null)
            {
                return payment;
            }

           if (String.Compare(payment.RefundPayment, "refund", true) != 0 )
            {
                return payment;
            }

        }

        Payment finalPayment = null;
        foreach (Payment testpayment in Order.payments)
        {
            if (testPayment.Customer.Name != customer.Name){continue;}

            if (testPayment.Cancelled) 
            {
                continue;
            }

            if (testPayment.RefundPayment != null) 
            {
                if (String.Compare(testPayment.RefundPayment, "refund", true) == 0 )
                {
                    continue;
                }
            }

            if (finalPayment == null)
            {
                finalPayment = testPayment;
            }
            else
            {
                if (testPayment.Value > finalPayment.Value)
                {
                    finalPayment = testPayment;
                }
            }
        }
       if (finalPayment == null) 
       {
           return payment;
       }

       return finalPayment;
    }

将其设为维基,以便代码爱好者可以回答而无需担心问题。

5 个答案:

答案 0 :(得分:2)

 if (testPayment.Customer.Name != customer.Name){continue;}

开始时不应该这样 - 当然,针对任何给定订单的所有付款都与同一客户有关?

我根本不喜欢这个功能,如果我通过了pay_id传递,那么我只希望获得特定付款,或者无效...这些搜索都没有... < / p>

听起来我觉得你需要考虑重新设计很多代码,我认为它远远超出了这个特定的功能......

答案 1 :(得分:1)

它将高度依赖数据。您需要使用“典型”数据集对其进行分析,找出瓶颈,然后根据您的配置文件数据考虑适当的优化。

答案 2 :(得分:1)

如果您可以向Payment类添加成员,请添加didRefund布尔值,只要RefundPayment字符串设置为“退款”,该布尔值就会设置为true。这允许您避免字符串比较。

在循环之前,如果你像这样初始化finalPayment

finalPayment = new Payment;
finalPayment.Value = -1.0e12

然后你可以避免循环中的空测试。 (假设没有一个客户正在支付十亿美元的负债)

答案 3 :(得分:1)

第一次测试(if (payment.RefundPayment == null))是多余的。 使用String.Compare的第二个测试使用空字符串。您可以在foreach循环中使用此“比较”的第二位使用此“优化”。

答案 4 :(得分:1)

你可以将其中一个条件移动到它自己的函数中,因为它重复了两次(测试它和它的相反)。您还可以将条件推到一起并将整个循环包装在第一个条件中。这样你只有一个函数的退出点。如果这看起来不可管理,你可以将foreach-loop包装成一个函数,然后就这样调用它。

private static boolean IsRefundPayment(Payment payment) {
    return payment.RefundPayment != null && String.Compare(payment.RefundPayment, "refund", true) == 0;
}

private static Payment FindPayment(Order order, Customer customer, int paymentId) {
    Payment payment = Order.Payments.FindById(paymentId);
    if (payment == null || IsRefundPayment(payment)) {
        foreach (Payment testpayment in Order.payments) {
            if (testPayment.Customer.Name == customer.Name && !testPayment.Cancelled && !IsRefundPayment(payment)
                && (testPayment.Value > payment.Value)) {
                payment = testPayment;
            }
        }
    }
    return payment;
}