Introduction
Working with collections efficiently is a cornerstone of C# development. This article demonstrates practical ways to handle importing, searching, and sorting data while considering performance optimizations. Instead of relying on external dependencies like CSV files or frameworks like WPF, we’ll focus purely on the logic and concepts of working with collections.
We’ll use a simple example: managing a list of countries. Let’s walk through setting up the data, searching for specific countries, sorting them, and optimizing performance.
Step 1: Define the Data Model
To start, we need a Country
class to represent the data. It will have three properties: the country’s name, code, and continent. Additionally, we’ll override the ToString
method to provide a readable format for display.
public class Country
{
public string Name { get; set; }
public string Code { get; set; }
public string Continent { get; set; }
public override string ToString()
{
return $"{Name} ({Code}) - {Continent}";
}
}
Step 2: Populate the Collection
Instead of importing data from an external file, we’ll create a hardcoded list of countries for simplicity.
var countries = new List<Country>
{
new Country { Name = "Germany", Code = "DEU", Continent = "Europe" },
new Country { Name = "United States", Code = "USA", Continent = "North America" },
new Country { Name = "India", Code = "IND", Continent = "Asia" },
new Country { Name = "Malta", Code = "MLT", Continent = "Europe" },
new Country { Name = "Japan", Code = "JPN", Continent = "Asia" }
};
-
Why hardcode the data?
- This keeps the focus on the collection operations themselves without introducing complexities from external file handling.
Step 3: Searching for a Country
Using Linear Search (O(n))
A common approach is to use the List<T>.Find
method, which performs a linear search through the list.
public static Country GetCountryWithCode(string code, List<Country> countries)
{
if (code.Length != 3) return null; // Validate input length
return countries.Find(c => c.Code.Equals(code, StringComparison.OrdinalIgnoreCase));
}
Usage Example:
var country = GetCountryWithCode("IND", countries);
if (country != null)
{
Console.WriteLine($"Found: {country}");
}
else
{
Console.WriteLine("Country not found.");
}
-
Performance Insight:
-
Find
performs a linear search with O(n) complexity. This works fine for small datasets but can slow down for larger collections.
-
Step 4: Optimizing Search with a Dictionary
To improve search performance, use a Dictionary<TKey, TValue>
for constant-time lookups (O(1)).
var countryDict = countries.ToDictionary(c => c.Code);
public static Country GetCountryWithCode(string code, Dictionary<string, Country> countryDict)
{
countryDict.TryGetValue(code.ToUpper(), out var country);
return country;
}
Usage Example:
var optimizedCountry = GetCountryWithCode("USA", countryDict);
if (optimizedCountry != null)
{
Console.WriteLine($"Found: {optimizedCountry}");
}
else
{
Console.WriteLine("Country not found.");
}
-
Performance Benefit:
- Using a dictionary drastically reduces search time, making it ideal for large datasets or frequent lookups.
Step 5: Sorting the Collection
Using LINQ’s OrderBy
:
For sorting, LINQ provides a clean and simple solution with the OrderBy
method.
var sortedCountries = countries.OrderBy(c => c.Name).ToList();
Usage Example:
Console.WriteLine("Sorted Countries:");
foreach (var country in sortedCountries)
{
Console.WriteLine(country);
}
-
Performance Insight:
- Sorting algorithms like the one used in
OrderBy
typically have O(n log n) complexity, which is efficient for most scenarios. - While
List.Sort
is faster, the readability and simplicity of LINQ makeOrderBy
a great choice for one-time operations.
- Sorting algorithms like the one used in
Step 6: Putting It All Together
Here’s the complete example code, combining everything:
using System;
using System.Collections.Generic;
using System.Linq;
public class Country
{
public string Name { get; set; }
public string Code { get; set; }
public string Continent { get; set; }
public override string ToString()
{
return $"{Name} ({Code}) - {Continent}";
}
}
class Program
{
static void Main()
{
// Step 2: Populate the collection
var countries = new List<Country>
{
new Country { Name = "Germany", Code = "DEU", Continent = "Europe" },
new Country { Name = "United States", Code = "USA", Continent = "North America" },
new Country { Name = "India", Code = "IND", Continent = "Asia" },
new Country { Name = "Malta", Code = "MLT", Continent = "Europe" },
new Country { Name = "Japan", Code = "JPN", Continent = "Asia" }
};
// Step 3: Search with linear search
var country = GetCountryWithCode("IND", countries);
Console.WriteLine(country != null ? $"Found: {country}" : "Country not found.");
// Step 4: Optimize search with dictionary
var countryDict = countries.ToDictionary(c => c.Code);
var optimizedCountry = GetCountryWithCode("USA", countryDict);
Console.WriteLine(optimizedCountry != null ? $"Found: {optimizedCountry}" : "Country not found.");
// Step 5: Sort the collection
var sortedCountries = countries.OrderBy(c => c.Name).ToList();
Console.WriteLine("Sorted Countries:");
foreach (var sortedCountry in sortedCountries)
{
Console.WriteLine(sortedCountry);
}
}
public static Country GetCountryWithCode(string code, List<Country> countries)
{
if (code.Length != 3) return null;
return countries.Find(c => c.Code.Equals(code, StringComparison.OrdinalIgnoreCase));
}
public static Country GetCountryWithCode(string code, Dictionary<string, Country> countryDict)
{
countryDict.TryGetValue(code.ToUpper(), out var country);
return country;
}
}
Conclusion
In this article, we covered:
- How to define and populate a collection with a simple
Country
class. - Searching for elements using both
List<T>.Find
andDictionary<TKey, TValue>
. - Sorting collections using LINQ’s
OrderBy
.
By focusing on performance and clean code, you can handle collections effectively in your applications. Experiment with these techniques to optimize your projects and gain a deeper understanding of C# collections!
Top comments (0)