Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace two foreach loops with linq

Tags:

c#

linq

I have a two foreach loops and need to replace with linq to overcome performance issues.

List<string> stringList = new List<string>();
foreach (var item in list)
{
    foreach (var inneritem in item)
    {
        stringList.Add(inneritem.data1)
    }
}

List<string> stringList = new List<string>();
foreach (var item in list)
{
    foreach (var inneritem in item)
    {
        stringList.Add(inneritem.data1)
    }
}

data1 string data is added to stringList.

like image 406
bmdprasad Avatar asked Dec 05 '22 09:12

bmdprasad


1 Answers

LINQ will make the code cleaner, not faster. Inserting 1M items in a List will cause 20 reallocations and create 19 big temporary buffers if done carelessly.

Each time a list's internal buffer runs out, the List will create a new buffer twice as large and copy the old data over. The old buffer will remain in memory until the garbage collector runs. This can lead to a lot of big temporary buffers in memory and even an OutOfMemoryException if memory becomes so fragmented that .NET's allocator can't find a big enough memory range for a new buffer.

Cleaning up

One way is to use LINQ is to use two from clauses :

var query = from item in list
            from innerItem in item
            select innerItem.data1;
var results=query.ToList();

Another way is to use SelectMany to flatten a nested enumerable, eg :

var results = list.SelectMany(item=>item)
                 .Select(inner=>inner.data1)
                 .ToList();

Performance

To avoid reallocations, the list should be created in advance with a predefined capacity. The capacity doesn't have to be accurate.

If we expect eg 10K items, we can create a list with a capacity of 10K items and fill it in a loop:

var results=new List<string>(10000);
var query = from item in list
            from innerItem in item
            select innerItem.data1;
foreach(var item in query)
{
    results.Add(item);
}    
like image 81
Panagiotis Kanavos Avatar answered Dec 08 '22 11:12

Panagiotis Kanavos