【问题标题】:compare nested json collections using C# LINQ使用 C# LINQ 比较嵌套的 json 集合
【发布时间】:2016-06-02 05:57:08
【问题描述】:

我需要使用 C# linq 将嵌套的 json 集合相互比较。这是 json 集合的示例 以及他们绑定的类。

=== 集合 1 ===

[
    {
        "contractId": "100-200-A",
        "invoices": [
            {
                invoiceNumber: 987654
            },
            {
                invoiceNumber: 555999
            }           
        ]
    },
    {
        "contractId": "300-777-Z",
        "invoices": [
            {
                invoiceNumber: 12345
            },
            {
                invoiceNumber: 100025
            }           
        ]
    }
]

public class Contract
{
    public string ContractId { get; set; }
    public IList<Invoice> Invoices { get; set; }

    public class Invoice 
    {
        public int InvoiceNumber { get; set; }
    }
}

=== 集合 2 ===

[
    {
        "paymentDate": "01/01/2000",
        "contracts":[
            {
                "contractId": "100-200-A",
                "invoices": [
                    {
                        invoiceNumber: 987654
                    },
                    {
                        invoiceNumber: 555999
                    },
                    {
                        invoiceNumber: 444333
                    },
                    {
                        invoiceNumber: 111000
                    }
                ]
            },
            {
                "contractId": "300-777-Z",
                "invoices": [
                    {
                        invoiceNumber: 12345
                    },
                    {
                        invoiceNumber: 100025
                    },
                    {
                        invoiceNumber: 888666
                    },
                    {
                        invoiceNumber: 222999
                    }                   
                ]
            }
        ]
    }
]

public class PaymentRequest
{
    public DateTime PaymentDate { get; set; }
    public IList<ContractList> Contracts { get; set; }
    public class ContractList
    {       
        public string ContractId { get; set; }  
        public IList<InvoiceList> Invoices { get; set; }
    }

    public class InvoiceList
    {          
        public int InvoiceNumber { get; set; }
    }
}

假设两个集合中的 contractId 相同,我可以在两者之间创建一个 linq 连接,我很难找到第二个集合集中的额外发票。本质上,我需要取回第二个集合中不存在于第一个集合中的特定contractId的所有发票编号的列表。

【问题讨论】:

  • 为什么同一件事有两个不同的类? Invoice vs InvoiceListContract vs ContractList?
  • 有效问题。为简洁起见,处理现有实现和许多类属性(来自两者)被忽略了

标签: c# .net linq


【解决方案1】:

你要求的是antijoin。相应的 LINQ 构造是 group join 并检查空内部组。见How can I use LINQ to avoid calling Contains() inside a Where() clause?

将其应用于您的用例(假设与您之前的问题中的数据结构相同)可能是这样的:

var query =
    from request in (
        from contract in paymentRequest.Contracts
        from invoice in contract.Invoices
        select new { contract, invoice }
    )
    join valid in (
         from contract in validContracts
         from invoice in contract.InvoiceList
         select new { contract, invoice }
    )
    on new { request.contract.ContractId, request.invoice.InvoiceNumber }
    equals new { valid.contract.ContractId, valid.invoice.InvoiceNumber }
    into validRequests
    where !validRequests.Any()
    select request;

【讨论】:

    【解决方案2】:

    试试这个:

    foreach (var contract in payment.Contracts)
    {
        var otherContract = contracts.First(c => c.ContractId == contract.ContractId);
        var missingInvoiceNumbers = contract.Invoices.Where(i => !otherContract.Invoices.Any(inv => inv.InvoiceNumber == i.InvoiceNumber))
                                                     .Select(i => i.InvoiceNumber);
        // do something with the results, like adding them to a dictionary <contract.ContractId, missingInvoiceNumbers>
    }
    

    它不是纯 LINQ,但最好让它在未来可读。

    【讨论】:

      【解决方案3】:

      找到第二个收集集中的额外发票

      让我们将 list1 和 list2 称为您需要比较的联系人列表。 linq 应该是这样的:

      list1.Join(list2, x=>x.ContactId, x=>x.ContactId, 
          (c1,c2)=>new {
              c2.ContactId,
              MissingInv=c2.Invoices.Where(x=>c1.Invoices.All(y=>x!=y))
          });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-09-03
        • 2014-12-10
        • 1970-01-01
        • 1970-01-01
        • 2013-04-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多