2
public class APIBillingHistory
{        
    public List<APIBillingHistoryDetails> BillingHistoryDetails;
}

public class APIBillingHistoryDetails
{   
    public List<APIBillingHistoryPaymentType> PaymentType;
    public string BillId;
}

public class APIBillingHistoryPaymentType
{
    public string Description;
    public Decimal Principal;
}

I have a class of nested list objects. I would like to merge respective PaymentList collection to its parent list APIBillingHistoryDetails

For example:

APIBillingHistory
-----BillingHistoryDetails
        Bill ID : 123
        ----PaymentType
                Description : "A"
                Principal : 100
        ----PaymentType
                Description : "B"
                Principal : 200
-----BillingHistoryDetails
        Bill ID : 123
        ----PaymentType
                Description : "A"
                Principal : 150
        ----PaymentType
                Description : "B"
                Principal : 300

Let's say I have sample date specified above. I would like to have resulted in the following format. Here I am merging PaymentList by adding Principal attribute for each Description values if they have same bill Id

The output should look like this:

APIBillingHistory
-----BillingHistoryDetails
        Bill ID : 123
        ----PaymentType
                Description : "A"
                Principal : 250
        ----PaymentType
                Description : "B"
                Principal : 500
1
  • 1
    I'm sure you tried things yourself. Could you indicate where you got stuck? Commented Jun 23, 2017 at 6:52

3 Answers 3

3
+50

This will give the desired output

var merged = new APIBillingHistory {
    BillingHistoryDetails = history
        .BillingHistoryDetails
        .GroupBy(detail => detail.BillId) //Group same bill Ids
        .Select(detailGroup => new APIBillingHistoryDetails {
            BillId = detailGroup.Key,
            PaymentType = detailGroup.SelectMany(p => p.PaymentType) //Get all payments
                .GroupBy(pymtType => pymtType.Description) //and group them by description
                .Select(pymtTypeGroup => new APIBillingHistoryPaymentType { //construct payment type
                    Description = pymtTypeGroup.Key,
                    Principal = pymtTypeGroup.Sum(t => t.Principal) // summing all grouped principals
                }).ToList()
        }).ToList()
};

Given

var history = new APIBillingHistory {
    BillingHistoryDetails = new List<APIBillingHistoryDetails> {
         new APIBillingHistoryDetails {
              BillId = "123",
              PaymentType = new List<APIBillingHistoryPaymentType>{
                  new APIBillingHistoryPaymentType {
                     Description = "A",
                     Principal = 100
                  },
                  new APIBillingHistoryPaymentType {
                     Description = "B",
                     Principal = 200
                  }
              }
         },
         new APIBillingHistoryDetails {
              BillId = "123",
              PaymentType=new List<APIBillingHistoryPaymentType>{
                  new APIBillingHistoryPaymentType {
                     Description = "A",
                     Principal = 150
                  },
                  new APIBillingHistoryPaymentType {
                     Description = "B",
                     Principal = 300
                  }
              }
         }
     }
};
Sign up to request clarification or add additional context in comments.

Comments

2

I know it's ugly but at least it works :)

List<APIBillingHistoryDetails> newList = (from item in BillingHistoryDetails.GroupBy(t => t.BillId)
    let paymentType = item
        .SelectMany(t => t.PaymentType)
        .GroupBy(t => t.Description)
        .Select(t => new APIBillingHistoryPaymentType
        {
            Description = t.Key.Description,
            Principal = t.Sum(s => s.Principal)
        })
        .ToList()
    select new APIBillingHistoryDetails
    { 
        BillId = item.Key,
        PaymelntType = paymentType
    }
).ToList();

Comments

0

So you have an ApiBillingHistory, which has zero or more ApiBillingHistoryDetails, And each APIBillingHistoryDetail has zero or more APIBillingHistoryPaymentTypes.

And you want to group all ApiBillingHistoryDetails with the same Id into one ApiBillingHistoryDetail, with PaymentTypes that are groups of all ApiBillingHistoryPaymentTypes with the same Description and the sum of all Principal values of the elements in the group.

You didn't mention what you want if one ApiBillingHistoryDetail contains an Id that is not in any of the other ApiBillingHistoryDetail. Also not if one PayMentType description is not in the other paymentTypes.

 // take all BillingHistoryDetails
var groups = ApiBillingHistory.BillingHistoryDetails
    // group them into groups of items with the same Id
   .GroupBy(
        // Key of the group is this same Id
        historyDetail => historyDetail.Id,
        // elements of the group:
        // group all payment types of the history detail
        // into subgroups of items with the same Description
        historyDetail => historyDetail.PaymentTypes.GroupBy( 
                // Key of subgroup: the Description                                  
                paymentType => payMentType.Description,
                // elements of the gorup = the Principal
                // of the paymentTypes with this description
                paymentType => paymentType.Principal), 

             // now we have sub groups of Principals from all paymentTypes
             // with a Description equal to the sub group.
             // convert every sub Group into one PaymentType:
             .Select(subGroup => new PaymentType()
             {
                 Description = subGroup.Key,
                 Principal = subGroup.Sum(),
             }))

       // so now we have Groups
       // with a Key historyDetail.Id
       // and as elements the list of PaymentTypes
       // where each payMentType contains the Description and the sum of all
       // payment types with this description
       // convert to billingHistoryDetails:
       .Select(mainGroup => new BillingHistoryDetails
       {
          // Id is the Key of the group
          Id = mainGroup.Key,
          // PaymentType is the list of created PaymentTypes
          PaymentType = mainGroup.ToList(),
       });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.