C# 12 LINQ Partitioning

GuruPrakashGuruPrakash
5 min read

I've seen many developers use complicated nested loops when LINQ set operations could have achieved the same result in just one line. Today, I'm excited to share these powerful yet often overlooked LINQ features that have saved me a lot of coding time.

What is Partitioning in LINQ?

Partitioning in LINQ involves dividing a sequence into distinct sections without changing the order of the elements, similar to splitting a deck of cards at specific points while keeping the original order intact.

What are C# LINQ Partitioning Operators?

Getting the First N Elements - Take(n)

The Take operator is your best friend when you want to grab a certain number of elements from the start of a sequence. Here's a quick and easy example (Edit in .NET Fiddle):

var numbers = Enumerable.Range(1, 10);
var firstThree = numbers.Take(5);

// Result: 1, 2, 3, 4, 5

This is especially helpful for features such as:

  • Creating preview sections of content

  • Displaying “top N” items in a dashboard

  • Limiting API results

Starting from N - Skip(n)

The Skip operator is like the perfect partner to Take. It lets you skip over a certain number of elements and then work with what's left. Here's how it works (Edit in .NET Fiddle):

var numbers = Enumerable.Range(1, 10);
var firstThree = numbers.Skip(5);

// Result: 6,7,8,9,10
  • Process data in smaller chunks

  • Skip the first few elements if they're headers or metadata.

  • Set up pagination

Conditional Partitioning - TakeWhile(expression) & SkipWhile(expression)

TakeWhile and SkipWhile provide flexibility by allowing you to take or skip elements based on a condition instead of a fixed number (Edit in .NET Fiddle).

var numbers = Enumerable.Range(1, 10);
var twNos = numbers.TakeWhile(n => n < 5);
var swNos = numbers.SkipWhile(n => n < 6);
Console.WriteLine("TakeWhile: ");
foreach(var n in twNos) Console.Write($"{n},");
Console.WriteLine("\n");
Console.WriteLine("SkipWhile: ");
foreach(var n in swNos) Console.Write($"{n},");
  • Filtering out initial data that does not meet your criteria

  • Processing data until a specific condition is satisfied.

  • Partition sorted collections based on values to efficiently organize or process data.

Conditional Partitioning - TakeLast(n) & SkipLast(n)

Edit in .NET Fiddle

var numbers = Enumerable.Range(1, 20);
var tlNos = numbers.TakeLast(10);
var slNos = numbers.SkipLast(10);

Console.WriteLine("SkipLast: ");
foreach(var n in slNos) Console.Write($"{n},");
Console.WriteLine("\n");
Console.WriteLine("TakeLast: ");
foreach(var n in tlNos) Console.Write($"{n},");

Working with Batches - Chunk

The Chunk operator is a recent addition to LINQ that allows you to divide your sequence into smaller, equally-sized groups, making it highly beneficial for batch processing (Edit in .NET Fiddle).

var numbers = Enumerable.Range(1, 10);
var nos = numbers.Chunk(5);
int i = 0;
foreach(int[] n in nos) {
    Console.WriteLine($"\n\nChunks #{i+1}: \n");
    foreach(int n1 in n) Console.Write($"{n1},");
    Console.WriteLine("\n");
    foreach(int n2 in n) Console.Write($"{n2},");
    i+=1;
}

Eliminating Duplicates - Distinct()

The Distinct operator is essential when you need to make sure every item in a collection is unique. Imagine a situation where your data has duplicate entries, such as a list of products that appear in multiple categories (Edit in .NET Fiddle).

int[] numbers = [0,10,3,6,7,8,9,5,6,1,2,6,3,5,4,7,9,8,0,11];
var nos = numbers.Distinct().Order();
foreach(int n in nos) Console.Write($"{n},");

This example selects only unique numbers. By utilizing the Distinct, you eliminate redundant data and improve processing speed, particularly when handling large collections.

Also read our other articles on C#

Practical Example of Partitioning in LINQ using C# 12

using System;
using System.Collections.Generic;
using System.Linq;

public class PaginationExample
{
    public static void Main()
    {
        // Sample data
        List<string> items = new List<string>
        {
            "Item1", "Item2", "Item3", "Item4", "Item5",
            "Item6", "Item7", "Item8", "Item9", "Item10"
        };

        int currentPage = 1;
        int pageSize = 3;

        // Get data for the current page
        List<string> pagedItems = GetPagedData(items, currentPage, pageSize);

        // Display paged items
        Console.WriteLine($"Page {currentPage}:");
        foreach (string item in pagedItems)
        {
            Console.WriteLine(item);
        }
    }

    public static List<T> GetPagedData<T>(List<T> source, int page, int pageSize)
    {
        return source.Skip((page - 1) * pageSize).Take(pageSize).ToList();
    }
}

Where should you use LINQ Partitioning?

  • Address cases where data doesn't perfectly fit the partition size, like the last incomplete chunk or uneven pages.

  • Using IQueryable, LINQ queries execute only when accessed, making them ideal for partitioned queries.

  • Be aware of data size, particularly when using multiple operators such as Distinct and Chunk together.

Real World Applications of LINQ Partitioning

Partitioning data in LINQ is particularly helpful in situations like handling incomplete data chunks, managing uneven pages, and efficiently executing queries with IQueryable.

Batch Processing:

In ETL scenarios, partitioning is super important for breaking down data into manageable parts.

Parallel Processing:

With Chunk(), you can easily spread the workload across multiple threads.

Unique Data Extraction:

Using Distinct() is a great way to remove duplicates from your data, which makes analytics or reporting quicker and more dependable.

Pagination:

Showing a few items per page helps keep applications quick and responsive, while also cutting down on load times.

Also read our other articles on C#

Conclusion

LINQ partitioning operators provide a robust approach for selective data retrieval and manipulation within collections. These operators enable efficient data processing, particularly when handling large datasets or implementing features like data paging and filtering.

The application of LINQ partitioning techniques significantly enhances data management capabilities in .NET applications, allowing developers to manage large collections with precision. Operators such as Take, Skip, Distinct, and Chunk offer flexibility in data segmentation, deduplication, and chunking, thereby promoting optimized performance and maintainability.

Utilizing these operators effectively facilitates the targeted extraction of data subsets, minimizing unnecessary processing overhead and improving application efficiency. This approach is especially beneficial in scenarios requiring detailed data control, such as implementing pagination in user interfaces or executing complex data analysis tasks.

This article discusses how using LINQ partitioning operators like Take, Skip, Distinct, and Chunk in C# can streamline data handling, improve efficiency, and enhance performance in tasks such as pagination and batch processing by optimizing data segmentation and minimizing unnecessary processing.

The post LINQ Partitioning in C# 12 appeared first on DEVstoc.

0
Subscribe to my newsletter

Read articles from GuruPrakash directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

GuruPrakash
GuruPrakash