1. Giriş
Əgər sənin heç vaxt corab dolabın olubsa və orada cüt tapmağa çalışmısansa, artıq sıralama problemini yaşamısan. Hər şey qarışıq olanda, lazım olan şeyi tapmaq əsl questə çevrilir. Proqramlaşdırmada kolleksiyalarla da eyni vəziyyətdir.
Sıralama — bu, kolleksiyadakı elementləri müəyyən bir kriteriyaya görə (məsələn, əlifba, dəyər, tarix və s.) düzülüşdürmək prosesidir. Bu vacibdir:
- İstifadəçiyə məlumatları göstərmək üçün (heç kim xaosu sevmir).
- Axtarışı asanlaşdırmaq üçün (məsələn, binary search ancaq sıralanmış kolleksiyalarda işləyir).
- Müqayisə, hesabat, export və digər əməliyyatlar üçün.
Milyonluq sual: "Əgər məndə cəmi beş element varsa, sıralamağa ehtiyac yoxdur?" — Teorik olaraq, bəli, amma beş beş yüzə və ya beş minə çevriləndə, avtomatlaşdırma olmadan keçinmək olmur.
.NET-də sıralama üçün iki əsas yanaşma var:
- Orijinal kolleksiyanı dəyişmək (məsələn, List<T>-i Sort metodu ilə sıralamaq).
- Kolleksiyanın yeni sıralanmış kopyasını yaratmaq (məsələn, massiv klonlamaq, sonra sıralamaq).
.Sort() metodu ilə listlərin sıralanması
Sort() metodu List<T> sinfində var, çünki bu sinif IList<T> interfeysini implement edir və indekslə giriş və elementlərin sırasını dəyişmək imkanı verir.
Nümunə — ədədlərin artan sırada sıralanması:
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var numbers = new List<int> { 5, 2, 9, 1, 5, 6 };
numbers.Sort();
Console.WriteLine("Artan sırada sıralama:");
foreach(var number in numbers)
{
Console.Write($"{number} "); // 1 2 5 5 6 9
}
}
}
Burada "yerində" sıralama gedir: orijinal numbers listi dəyişir, elementlər yerini dəyişir.
Sətirlərin sıralanması
Sıralama sətirlər üçün də əla işləyir:
var words = new List<string> { "apelsin", "alma", "banan", "armud" };
words.Sort();
Console.WriteLine(string.Join(", ", words)); // apelsin, armud, banan, alma
Maraqlı fakt: default olaraq sətir sıralaması Unicode qaydasına görə gedir, "insan" əlifbasına görə yox (xüsusilə fərqli dillər üçün, çoxdilli tətbiqlərdə bunu nəzərə al).
2. Öz qaydalarına görə sıralama
Bəzən "default" sıralama uyğun olmur. Tutaq ki, istifadəçiləri ada görə yox, yaşa və ya qeydiyyat tarixinə görə sıralamaq istəyirsən.
Lambda ifadəsi ilə sıralama (Sort(Comparison<T>) metodu)
Sort metodunu elə çağırmaq olar ki, xüsusi sıralama qaydası — iki elementin müqayisə funksiyasını ötürəsən.
İstifadəçiləri yaşa görə sıralamaq:
class User
{
public string Name { get; set; }
public int Age { get; set; }
}
// ...
var users = new List<User>
{
new User { Name = "Alisa", Age = 30 },
new User { Name = "Bob", Age = 25 },
new User { Name = "Eva", Age = 35 }
};
users.Sort((u1, u2) => u1.Age.CompareTo(u2.Age));
foreach (var user in users)
{
Console.WriteLine($"{user.Name}: {user.Age}");
}
// Çıxış:
// Bob: 25
// Alisa: 30
// Eva: 35
Bu magiya necə işləyir? (u1, u2) => u1.Age.CompareTo(u2.Age) lambda-sı mənfi qaytarırsa, u1 daha cavan, müsbət — daha yaşlı, 0 — yaşlar bərabərdir.
IComparer<T> interfeysindən istifadə
Bəzən sıralama qaydasını ayrıca sinfə çıxarmaq istəyirsən, məsələn, çox kolleksiyan və ya mürəkkəb məntiqin varsa.
class UserAgeComparer : IComparer<User>
{
public int Compare(User x, User y)
{
return x.Age.CompareTo(y.Age);
}
}
// ...
var users = new List<User>{ /* ... */ };
users.Sort(new UserAgeComparer()); // indi yaşa görə sıralanır
Bu rahatdır, əgər proqramın müxtəlif yerlərində sıralama lazımdırsa və ya bir neçə fərqli qayda varsa.
Bir neçə sahə üzrə əl ilə sıralama
Əgər bəzi istifadəçilərin yaşı eynidirsə, amma həmin yaş qrupunda onları ada görə sıralamaq istəyirsənsə:
users.Sort((u1, u2) => {
int ageCompare = u1.Age.CompareTo(u2.Age);
if (ageCompare != 0)
return ageCompare;
else
return u1.Name.CompareTo(u2.Name);
});
İndi əvvəlcə yaşa, sonra ada görə sıralanır.
3. Kolleksiyanın kopyasını sıralamaq (orijinalı dəyişmədən)
Əgər orijinal listi dəyişmək istəmirsənsə, sıralamadan əvvəl onu kopyala:
var copy = new List<int>(numbers);
copy.Sort();
Custom obyektlər üçün də eyni:
var usersCopy = new List<User>(users);
usersCopy.Sort((a, b) => a.Age.CompareTo(b.Age));
4. Massivlərin sıralanması
Massivlərlə (T[]) də hər şey sadədir:
int[] numbers = { 4, 2, 9, 7 };
Array.Sort(numbers); // orijinal massiv dəyişir
"Custom" sıralama üçün:
Array.Sort(numbers, (a, b) => b.CompareTo(a)); // azalan sırada sıralama
Diqqət et, Array.Sort orijinal massivi dəyişir, yeni massiv qaytarmır. Əgər orijinalı saxlamaq lazımdırsa, əvvəlcədən kopyala:
int[] oldNumbers = { 3, 2, 1 };
int[] copy = (int[])oldNumbers.Clone();
Array.Sort(copy);
5. Dictionary-lərin "sıralanması" (Dictionary<TKey, TValue>)
Dictionary<TKey, TValue> — mahiyyətcə sırasız kolleksiyadır (yəni, iterasiya zamanı qayda zəmanət verilmir). Amma bəzən "sıralanmış cütlər" almaq istəyirsən.
Sıralanmış açar və ya dəyərlər almaq üçün, cütləri listə kopyala və istədiyin kimi sıralama apar:
var dict = new Dictionary<string, int>
{
{ "alma", 2 },
{ "apelsin", 5 },
{ "armud", 3 }
};
// Açar üzrə sıralama:
var keyValueList = new List<KeyValuePair<string, int>>(dict);
keyValueList.Sort((a, b) => a.Key.CompareTo(b.Key));
foreach (var kv in keyValueList)
{
Console.WriteLine($"{kv.Key}: {kv.Value}");
}
// Dəyər üzrə sıralama:
keyValueList.Sort((a, b) => a.Value.CompareTo(b.Value));
foreach (var kv in keyValueList)
{
Console.WriteLine($"{kv.Key}: {kv.Value}");
}
Əgər sıralanmış açar və ya dəyərlər listi lazımdırsa:
var sortedKeys = new List<string>(dict.Keys);
sortedKeys.Sort();
var sortedValues = new List<int>(dict.Values);
sortedValues.Sort();
Amma unutma ki, Dictionary strukturu dəyişmir — sadəcə sıralanmış iterasiya alırsan. .NET 9-da OrderedDictionary<TKey, TValue> olacaq, hansı ki, elementlərin sırasını saxlayır. Tez-tez yox, amma bəzən belə struktur lazım olur.
6. Faydalı nüanslar
Müqayisə interfeysini implement etmək mütləqdir?
Sadə: əgər obyektlərin "özləri" necə müqayisə olunacağını "bilsin" istəyirsənsə (məsələn, tarixə və ya ada görə), IComparable<T> interfeysini implement et.
class Product : IComparable<Product>
{
public string Name { get; set; }
public decimal Price { get; set; }
public int CompareTo(Product other)
{
return Price.CompareTo(other.Price);
}
}
İndi belə edə bilərsən:
var products = new List<Product> { /* ... */ };
products.Sort(); // qiymətə görə sıralayır
Əgər default müqayisə uyğun deyilsə — IComparer<T> istifadə et və ya yuxarıda göstərildiyi kimi lambda ötür.
İstifadəçi siyahısını əlifba sırası ilə sıralamaq
Tutaq ki, tətbiqdə istifadəçi siyahısı var:
List<string> users = new List<string> { "Viktor", "Anna", "Ekaterina", "Boris" };
users.Sort(); // indi users sıralanıb: Anna, Boris, Viktor, Ekaterina
Tapşırıqları təciliyə görə sıralamaq
class Task
{
public string Title { get; set; }
public int Priority { get; set; } // 1 - təcili, 2 - vacib, 3 - gözləyə bilər
}
var todo = new List<Task>
{
new Task { Title = "Ev tapşırığını et", Priority = 2 },
new Task { Title = "Çörək al", Priority = 1 },
new Task { Title = "Seriala bax", Priority = 3 }
};
todo.Sort((a, b) => a.Priority.CompareTo(b.Priority));
foreach (var task in todo)
Console.WriteLine($"{task.Priority}: {task.Title}");
Sıralama üsullarının müqayisəsi
| Kolleksiya | Yerində dəyişir? | Sıralama metodu | Qayda vermək olar? |
|---|---|---|---|
|
Bəli | |
Bəli: lambda və ya IComparer |
|
Bəli | |
Bəli: lambda və ya IComparer |
|
Xeyr | — (list yaradıb sıralayırıq) | Bəli: lambda və ya IComparer ilə |
7. Tipik səhvlər və sıralama nüansları
Yerində sıralama — orijinal kolleksiyanı dəyişir! Əgər orijinal məlumat dəyişməməlidirsə — əvvəlcədən kopyala.
Dəyişməz kolleksiyanı sıralamağa cəhd (məsələn, ReadOnlyCollection<T>) runtime səhvinə gətirib çıxaracaq.
Sətirlərin müxtəlif mədəniyyətlərdə fərqli sıralanması: sətir sıralaması (xüsusilə kiril, umlaut və s.) müxtəlif lokalizasiya üçün fərqli ola bilər. Düzgün sıralama üçün Comparer.Create(...) istifadə et və lazımi mədəniyyəti seç.
Dictionary-lərin sıralanması strukturunu dəyişmir — həmişə yeni cütlər ardıcıllığı (və ya yeni list) qaytarılır.
Mürəkkəb qayda üçün öz məntiqinlə IComparer<T> interfeysindən istifadə et.
Səhv sıralama nümunəsi (praktik "tələ" kimi):
var numbers = new List<int> { 1, 2, 3 };
var sorted = numbers.Sort(); // SƏHV: Sort() void qaytarır!
Düzgün:
numbers.Sort(); // yerində numbers dəyişir
// Əgər yeni kolleksiya lazımdırsa:
var sorted = new List<int>(numbers);
sorted.Sort();
GO TO FULL VERSION