LinkedIn
Проекты
Advertisement
RSS
разработка сайтов
оптимизация сайта
веб-дизайн
продвижение сайтов
ASP.NET
ASP.NET MVC
.NET Core
HTML5
SEO
CSS3
jQuery
Bootstrap
Angular
React
Always will be ready notify the world about expectations as easy as possible: job change page

LINQ — How to avoid nested loops in C#

Created: 27 Oct 2022
Author: Sebastian Streng
Source: https://medium.com/@sebastianstreng96/linq-how-to-avoid-nested-loops-in-c-ed4ae19886e4
Views: 50

Writing code can be very exciting but it also can be very frustrating if your code is based on nested loops. Iterations are still one the most important parts of coding. So how can we avoid using ugly nested loops in our code?

LINQ — Language Integrated Query

Microsoft language developers provided a way to express queries directly in their languages. LINQ extends the language by the addition of query expressions, which are similar to SQL-queries.

LINQ syntax is typically less efficient than a foreach loop. It’s good to be aware of any performance tradeoff that might occur when you use LINQ. On the other hand, its the most efficiant way to improve the readability of your code.

Benefits of using LINQ

  • Developers can access new Technologies without knowing much about them.
  • LINQ offers an object-based, language-integrated way to query over data no matter where that data came from. So through LINQ we can query database, XML as well as collections.
  • create complete Applications with less code.
  • develop Application in less time and with fewer errors.
  • combine datasources without resorting to odd programming tricks.
  • Get new Developers working faster.
  • Compile time syntax checking.
  • allows you to query collections like arrays, enumerable classes etc in the native language of your application, like VB or C# in much the same way as you would query a database using SQL.

“Perhaps the most important aspect of LINQ which I’d love other API designers to take on board is that of how complicated queries are constructed from lots of little building blocks. What makes it particularly elegant is that the result of applying each building block is unchanged by anything else you do to it afterwards.

LINQ doesn’t enforce immutability of course — you can start off with a mutable list and change its content at any time, for example, or change the properties of one of the objects referenced within it, or pass in a delegate with side-effects — but LINQ itself won’t introduce side-effects.” (Skeet, 03.2018)

Methods:

Loops using index

One of the most common mistakes using LINQ is that developers think its not possible to replace a for-loop that calls methods based on its index. Here are some examples that shows how to do it.

int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

// bad code:
int c = 1;
for (int i = 0; i < numbers.Length; ++i)
{
    c *= numbers[i];
}

// good code:
int c2 = numbers.Aggregate(1, (current, t) => current*t);

//Combine Foreach-loop with index:
List<string> bestColleagues = new List<string>
{
    "Tobi", "Jan", "Sebastian"
};

foreach (var colleague in bestColleagues.Select((name, index) => (name, index)))
{
    Console.WriteLine($"{colleague.name} is number {colleague.index +1} on this list." );
}

// Get the index of the number 8.
var indexes = numbers
    .Select((x, i) => i)
    .Where((i) => numbers[i] == 8);

Nested loops using Linq

The first example takes about 17 lines. The second one just 3.

Lets imagine we need to navigate through an Excelworksheet using EPPlus. Using loops to access each individual cell can always be very expensive. Nested for-loops are often used here, which take up a lot of space and make reading complicated. Lets see how we can avoid nested loops:

private static void DoSomethingInExcel(ExcelWorksheet worksheet)
{
    // Now we need to navigate to a X/Y-System in Excel.
    // bad Code:
    var startRow = 1;
    var endrow = worksheet.Dimension.Rows;
    for (int row = startRow; row <= endrow; row++)
    {
        var startColumn = 1;
        var endColumn = worksheet.Dimension.Columns;
        for (int col = startColumn; col < endColumn; col++)
        {
            if (worksheet.Cells[row, col].Style.Font.Bold == true)
            {
                var cellContent = Convert
                    .ToInt32(worksheet.Cells[row, col].Value
                    .ToString());

                DoSomething(cellContent);
            }
        }
    }
    //--------------------------------------------------------------------------------

    // good Code:

     worksheet.Cells[worksheet.Dimension.Address]
        .Where(c => c.Style.Font.Bold)
        .Select(c => DoSomething(Convert.ToInt32(c)));
}

Conclusion

all in all, the advantages of Linq outweigh the disadvantages.
The loss of speed versus clean readability, faster writing, and application of SQL-based language suggests that using Linq-expressions offers powerful benefits to the developer.

Further Examples:

static void Main(string[] args)
{
    int[] randomNumbers = { 127, 264, 33657, 43, 535, 6, 83652, 73, 652, 3043, 236, 896 };

    // Filter array

    // BadPractice:
    List<int> numberslist = new ();
    foreach(int number in randomNumbers)
    {
        if (number.ToString().Contains("3")) {
            numberslist.Add (number);
        }
    }

    // Good Practice:
    var numberList2 = randomNumbers
        .Where(n => n.ToString().Contains("3"));

    // Now we can use Linq-expressions:

    // Get Every number until 999,
    // Call Method in Linq-expression,
    // Order every Element by Descending
    // and return first element of the list
    int firstElement = randomNumbers
         .Where(n => n.ToString().Length < 4)
         .Select(n => DoSomething(n))
         .OrderByDescending(n => n)
         .FirstOrDefault();

    // Using SelectMany() for Multi-Dimensional IEnumerable:
    // Get every Vehicle that contains a "a"
    var VehiclesThatContainsA = GetDoubleArray()
        .SelectMany(v => v)
        .Where(v => v.Contains("a"));
}

public static int DoSomething(int randomNumber)
{
    return randomNumber + 10;
}

public static IEnumerable<IEnumerable<string>> GetDoubleArray()
{
    List<string[]> vehicles = new ();
    string[] cars = {"Audi", "BMW", "Ford", "Porsche"};
    string[] motorcycles = { "Honda", "Suzuki", "BMW", "Yamaha"};
    string[] trucks = { "Mercedes-Actros", "Scania", "Iveco" };

    vehicles.Add(cars);
    vehicles.Add(motorcycles);
    vehicles.Add(trucks);

    return vehicles;
}
Similar
16 Apr 2022
Author: Matthew MacDonald
Sometimes it’s the little things that count.When .NET 6 dropped this November, a few top-line items grabbed all the attention. I’m talking about C# 10, hot reload, Blazor’s AOT compilation, and some serious inner loop performance improvements. All of them...
20 Oct 2022
Author: Ricardo Griffith
Schedule and run background jobs using this powerful frameworkDisclaimer: the image mentioned in this article is currently marked as preview. Opinions expressed therein are solely my own and do not express the views or opinions of my employer.Hangfire provides a...
3 Feb 2022
Author: Satish Chandra Gupta
What if programming languages were stocks? And you had to make a portfolio to fetch good returns in 2022?You probably have seen various surveys and analyses listing the most popular programming languages. Those cover the universe of programming languages, like...
8 Jul 2021
Author: Christophe Nasarre
In the context of helping the teams at Criteo to clean up our code base, I gathered and documented a few C# anti-patterns similar to Kevin’s publication about performance code smell. Here is an extract related to good/bad memory patterns.Even...
Send message
Email
Your name
*Message


© 1999–2022 WebDynamics
1980–... Sergey Drozdov
Area of interests: .NET | .NET Core | C# | ASP.NET | Windows Forms | WPF | Windows Phone | HTML5 | CSS3 | jQuery | AJAX | MS SQL Server | Transact-SQL | ADO.NET | Entity Framework | IIS | OOP | OOA | OOD | WCF | WPF | MSMQ | MVC | MVP | MVVM | Design Patterns | Enterprise Architecture | Scrum | Kanban