Thursday, November 3, 2022

[FIXED] How can I get data for parent list which can have it's child/nested list's empty while flattening using SelectMany in C#

Issue

I'm trying to flatten a List using SelectMany() method, the problem is the child/nested lists can have data or sometimes it can be empty. I want the lambda query to at least return the data of parent list i.e. InventoryCode & InventoryDescription, because the parent collection can never be empty. I tried below query, but result count is 0 when any of the child/nested lists are empty.

public class Share
{
   public string shareCode {get;set;}
   public int shareNumber  {get;set;}
}
public class ProductModel
{
   public string productCode {get;set;}
   public string productName{get;set;}
   public List<Share> share{get;set;}
}

public class InventoryModel
{
   public string inventoryCode {get;set;}
   public string inventoryDescription {get;set;}
   public List<Product> products {get;set;}
}

Note-InventoryModel is also used as list in some other model

The below code which I have written work's well when child list's are not empty, but it fails to return any data when any of the child list's is empty

var invenFlatList = lstInventory.SelectMany(x => x.products.SelectMany(y => y.shares.Select(z => new NewModel
            {
                inventoryCode = x.inventoryCode ,
                inventoryDescription = x.inventoryDescription ,
                productCode = y.productCode ,
                productName= y.productName,
                shareCode = z.shareCode ,
                shareNumber  = z.shareNumber  
            }))).ToList();

Solution

You can use following approach using DefaultIfEmpty with a fallback item:

List<NewModel> resultList = lstInventory
        .SelectMany(inv => inv.products
            .SelectMany(prod => prod.shares
                .Select(share => new NewModel
                {
                    inventoryCode = inv.inventoryCode,
                    inventoryDescription = inv.inventoryDescription,
                    productCode = prod.productCode,
                    productName = prod.productName,
                    shareCode = share.shareCode,
                    shareNumber = share.shareNumber
                })
              .DefaultIfEmpty(new NewModel
              {
                  inventoryCode = inv.inventoryCode,
                  inventoryDescription = inv.inventoryDescription,
                  productCode = prod.productCode,
                  productName = prod.productName,
                  shareCode = null,
                  shareNumber = 0
              })))
        .ToList();


Answered By - Tim Schmelter
Answer Checked By - Marie Seifert (PHPFixing Admin)

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.