Home > Software engineering >  C# LINQ flatten array based on int property
C# LINQ flatten array based on int property

Time:11-08

I have a list of order items with the given structure :

OrderItem { Id = 1,Name = "First Item", Quantity = 2 }
OrderItem { Id = 2,Name = "Second Item", Quantity = 2 }
OrderItem { Id = 3,Name = "Third Item", Quantity = 1 }

I want to flatten it to the following structure :

DBItem{ Id = 1,Name = "First Item" }
DBItem{ Id = 2,Name = "First Item" }
DBItem{ Id = 3,Name = "Second Item" }
DBItem{ Id = 4,Name = "Second Item" }
DBItem{ Id = 5,Name = "Third Item" }

Is there a way using LINQ Select many ?

CodePudding user response:

You can use Enumerable.Range to generate aditional records:

var dbItems = orderItems
    .OrderBy(oi => oi.Id) // ensure correct order
    .SelectMany(oi => Enumerable.Range(0, oi.Quantity), (oi, n) => oi) // records duplication
    .Select((oi, idx) => new DBItem // Select overload with index
    {
        Id = idx   1,
        Name = oi.Name,
    })
    .ToList();

CodePudding user response:

This seems quite straight forward to me:

var items = new[]
{
    new OrderItem { Id = 1,Name = "First Item", Quantity = 2 },
    new OrderItem { Id = 2,Name = "Second Item", Quantity = 2 },
    new OrderItem { Id = 3,Name = "Third Item", Quantity = 1 },
};

var dbItems =
    items
        .SelectMany(item => Enumerable.Repeat(item.Name, item.Quantity))
        .Select((name, index) => new DBItem { Id = index   1, Name = name });

dbItems

CodePudding user response:

var items = new List<OrderItem>
{
    new OrderItem { Id = 1,Name = "First Item", Quantity = 2 },
    new OrderItem { Id = 2,Name = "Second Item", Quantity = 2 },
    new OrderItem { Id = 3,Name = "Third Item", Quantity = 1 },
};
var dbitems = new List<DBItem>();
var counter = 1;

items.ForEach(item =>
{
    for (int i = 0; i < item.Quantity; i  )
    {
        dbitems.Add(new DBItem
        {
            Id = counter  ,
            Name = item.Name,
        });
    }
});
  • Related