You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 21:33:24