Karthik Arthik
Karthik Arthik

Reputation: 296

How to generate duplicate items in a list using LINQ?

this is LINQ query I have used

var result = (from price in inventoryDb.Pricing.AsNoTracking()               
              where price.Quantity > 0m
              select new
              {
                 TagNo = price.TagNo,
                 SellingRate = price.SellingRate,
                 Quantity = price.Quantity           
              }).ToList();

Based on the Quantity value I need to generate duplicate items in the list.

Output :

result = [0]{TagNo="100", SellingRate=1500.00, Quantity=1}
         [1]{TagNo="101", SellingRate=1600.00, Quantity=2}

Expected Result:

result = [0]{TagNo="100", SellingRate=1500.00}
         [1]{TagNo="101", SellingRate=1600.00}
         [2]{TagNo="101", SellingRate=1600.00}

Upvotes: 14

Views: 2664

Answers (2)

Gilad Green
Gilad Green

Reputation: 37299

Keeping with the query syntax just add a Enumerable.Repeat as follows:

var result = (from price in inventoryDb.Pricing.AsNoTracking()
              where price.Quantity > 0m
              from dup in Enumerable.Repeat(0,price.Quantity)
              select new
              {
                 TagNo = price.TagNo,
                 SellingRate = price.SellingRate,          
              }).ToList();

If indeed linq to entities does not support then add AsEnumerable like follows:

var result = (from price in inventoryDb.Pricing.AsNoTracking()
                                               .Where(p => p.Quantity > 0m)
                                               .AsEnumerable() //Loads only the filtered items to memory            
              from dup in Enumerable.Repeat(0,price.Quantity)
              select new
              {
                 TagNo = price.TagNo,
                 SellingRate = price.SellingRate,          
              }).ToList();

You can also use Enumerable.Range but because you do not use the value of that collection (and in my opinion also just that it describes better what you are doing) I decided just to go with Repeat

Upvotes: 5

Tim Schmelter
Tim Schmelter

Reputation: 460058

You can use Enumerable.SelectMany + Enumerable.Range:

var result = inventoryDb.Pricing.AsNoTracking()
    .Where(p => p.Quantity > 0m)
    .SelectMany(p => Enumerable.Range(0, p.Quantity)
        .Select(i => new
              {
                 TagNo = p.TagNo,
                 SellingRate = p.SellingRate      
              }))
    .ToList();

If that's not supported by your LINQ provider (f.e. Linq-To-Entities), the easiest is to use Linq-To-Objects. To avoid that all is loaded into memory you should use AsEnumerable after the Where:

var result = inventoryDb.Pricing.AsNoTracking()
    .Where(p => p.Quantity > 0m)
    .AsEnumerable()
    .SelectMany(p => Enumerable.Range(0, p.Quantity)
        .Select(i => new
              {
                 TagNo = p.TagNo,
                 SellingRate = p.SellingRate      
              }))
    .ToList();

Upvotes: 12

Related Questions