C#中如何高效识别同一ordernumber对应不同invoiceNumber的订单记录?
问题描述
我有一个包含ordernumber、invoiceNumber和itemnumber字段的OrderDetail类型列表,示例数据如下:
List<OrderDetail> lst=new List<OrderDetail>() { new OrderDetail{ ordernumber="O123", invoiceNumber="Inv123", itemnumber="I123"} }; lst.Add(new OrderDetail(){ ordernumber="O123", invoiceNumber="Inv124", itemnumber="I145" }); lst.Add(new OrderDetail(){ ordernumber="O456", invoiceNumber="Inv125", itemnumber="I145" }); lst.Add(new OrderDetail(){ ordernumber="O456", invoiceNumber="Inv125", itemnumber="I145" });
需求是:找出所有**同一ordernumber对应不同invoiceNumber**的记录,一旦发现就抛出错误。目前实现的代码如下:
List<string> lstOrders=lst.Select(x=>x.ordernumber).Distinct().ToList(); foreach(var order in lstOrders) { List<string> lstInvoice = lst.Where(x=>x.ordernumber==order).Select(x=>x.invoiceNumber).Distinct().ToList(); if(lstInvoice.Count >1) { throw new Exception($"订单号 {order} 对应多个不同的发票号"); } }
请问有没有更高效的实现方式?
更高效的实现方案
原代码需要多次遍历原列表(foreach循环中每次都要重新过滤),时间复杂度为O(n²),可以通过Linq的GroupBy一次性完成分组校验,将时间复杂度降到O(n),同时代码更简洁。
方案1:收集所有违规订单号后抛出错误
var invalidOrderNumbers = lst .GroupBy(detail => detail.ordernumber) .Where(group => group.Select(d => d.invoiceNumber).Distinct().Count() > 1) .Select(group => group.Key) .ToList(); if (invalidOrderNumbers.Any()) { throw new Exception($"违规订单号:{string.Join(", ", invalidOrderNumbers)},每个订单号只能对应一个发票号"); }
方案2:快速判断并抛出错误(无需收集所有违规项)
如果不需要知道具体哪些订单号违规,只想尽快终止流程抛出错误,可以直接用Any判断:
var hasInvalidOrders = lst .GroupBy(detail => detail.ordernumber) .Any(group => group.Select(d => d.invoiceNumber).Distinct().Count() > 1); if (hasInvalidOrders) { throw new Exception("存在订单号对应多个不同发票号的违规情况"); }
方案3:极致性能优化(提前终止遍历)
如果列表数据量极大,可以用HashSet在分组内提前终止判断——一旦发现分组内有第二个不同的发票号,就立即返回结果,无需遍历完整个分组:
var hasInvalidOrders = lst .GroupBy(detail => detail.ordernumber) .Any(group => { var invoiceSet = new HashSet<string>(); foreach (var detail in group) { invoiceSet.Add(detail.invoiceNumber); // 只要出现第二个不同的发票号,直接判定该分组违规 if (invoiceSet.Count > 1) { return true; } } return false; }); if (hasInvalidOrders) { throw new Exception("存在订单号对应多个不同发票号的违规情况"); }
内容的提问来源于stack exchange,提问作者A. A.
相关产品推荐
相关产品推荐

