1. Kolleksiyalarda axtarışın əsas imkanları
Çox vaxt “axtarış” və “filtrasiya” sözləri sinonim kimi qəbul olunur, amma proqramlaşdırmada bunlar fərqlənir.
- Filtrasiya — yəni kolleksiyadan müəyyən şərtə uyğun gələn bütün elementləri almaq istəyirik (məsələn, bütün ədədlər 10-dan böyükdür).
- Axtarış — adətən bizə bir element lazımdır: ilk uyğun gələn, müəyyən dəyəri olan element və ya sadəcə kolleksiyada olub-olmadığını bilmək.
Kitabxana ilə müqayisə etsək: filtrasiya — “Kosmos” mövzusunda bütün kitabları toplamaq kimidir, axtarış isə belə sual verməkdir: “Sizdə ‘Ulis’ kitabı var?” və ya “Mavi cildli ilk kitab haradadır?”.
.NET-in bütün əsas kolleksiyaları (massivlər, listlər, set-lər, dictionary-lər və s.) elementlərin axtarışı və ya mövcudluğunu yoxlamaq üçün bir neçə variant dəstəkləyir.
Gəlin ən məşhur metodlara baxaq:
| Kolleksiya | Mövcudluğu yoxla | İndeksi tap | Element tap | Açarla tap |
|---|---|---|---|---|
|
|
|
|
- |
(massiv) |
/ |
|
- | - |
|
|
- | - | - |
|
, |
- | - | İndeksatoru var |
Bəzi metodlar yalnız konkret tiplərdə mövcuddur.
2. List-lərdə axtarış: List<T>
List<T> — elementləri istənilən yerdən əldə etmək üçün ən universal kolleksiyalardan biridir. Əsas axtarış metodları bunlardır:
Elementin mövcudluğunu yoxlamaq: Contains
Bu metod siyahıda lazım olan elementin olub-olmadığını bildirir:
List<string> fruits = new List<string> { "Alma", "Banan", "Kivi" };
bool hasKiwi = fruits.Contains("Kivi"); // true
bool hasMango = fruits.Contains("Manqo"); // false
Console.WriteLine(hasKiwi); // True
Contains arxa planda sadəcə kolleksiyanı dövr edir və Equals metodundan istifadə edir.
İndeksi tapmaq: IndexOf
Elementin dəqiq harada olduğunu (siyahıdakı nömrəsini) bilmək lazımdırsa:
int index = fruits.IndexOf("Banan"); // 1 (indeksləmə sıfırdan başlayır)
int absentIndex = fruits.IndexOf("Qarpız"); // -1 (əgər element yoxdursa)
Console.WriteLine(index);
Console.WriteLine(absentIndex);
İlk uyğun gələn elementi tapmaq: Find
Konkret dəyərə görə yox, şərtə görə axtarmaq olar! Bunun üçün Find (və ya indeksli dostu — FindIndex) istifadə olunur:
// Adı 4 simvoldan uzun olan ilk meyvəni tap
string longFruit = fruits.Find(fruit => fruit.Length > 4); // "Alma"
Console.WriteLine(longFruit);
Diqqət: heç nə tapılmasa, tip üçün default dəyər qaytarılır (null referans tipləri üçün).
Bütün uyğun gələnləri tapmaq: FindAll
Əgər filtrasiya lazımdırsa (bütün uyğun gələnlər), FindAll istifadə et:
// Adında 'i' hərfi olan bütün meyvələr
List<string> withI = fruits.FindAll(f => f.Contains('i'));
foreach (var fruit in withI)
Console.WriteLine(fruit); // "Kivi"
3. Massivlərdə axtarış: Array sinfinin metodları
Massivlərdə Find metodu yoxdur (List-lərdəki kimi), amma onlar üçün statik Array sinfi var:
int[] numbers = { 1, 2, 3, 2, 4 };
int pos = Array.IndexOf(numbers, 2); // 1 — ilk 2-nin indeksi
int lastPos = Array.LastIndexOf(numbers, 2); // 3 — sonuncu indeks
Console.WriteLine(pos + ", " + lastPos);
Əgər şərtə görə element tapmaq lazımdırsa, sadə dövr istifadə et:
int firstGreaterThanTwo = -1;
for (int i = 0; i < numbers.Length; i++)
{
if (numbers[i] > 2)
{
firstGreaterThanTwo = numbers[i];
break;
}
}
Console.WriteLine(firstGreaterThanTwo); // 3
4. Bütün kolleksiyalar üçün universal metodlar
Çox kolleksiyalar axtarış üçün metodlar verir (məsələn, Contains, IndexOf, Find və s.). Daha mürəkkəb bir şey lazımdırsa, elementləri dövr etməklə özün yazırsan.
Nümunə: "B" ilə başlayan meyvə varmı?
bool hasB = false;
foreach (var f in fruits)
{
if (f.StartsWith("B"))
{
hasB = true;
break;
}
}
Console.WriteLine(hasB); // True
Nümunə: "i" olan ilk meyvəni tap
string withI = null;
foreach (var f in fruits)
{
if (f.Contains('i'))
{
withI = f;
break;
}
}
Console.WriteLine(withI); // "Kivi"
Nümunə: İstifadəçi obyektlərində axtarış
class Student
{
public string Name;
public int Group;
public int Id;
}
List<Student> students = new List<Student>
{
new Student { Name = "İvan", Group = 101, Id = 1 },
new Student { Name = "Mariya", Group = 101, Id = 2 },
new Student { Name = "Pyotr", Group = 102, Id = 3 },
};
// Id == 2 olan tələbəni tapırıq
Student maria = null;
foreach (var s in students)
{
if (s.Id == 2)
{
maria = s;
break;
}
}
if (maria != null)
Console.WriteLine(maria.Name); // "Mariya"
else
Console.WriteLine("Tələbə tapılmadı");
5. HashSet<T>-də axtarış: sadəcə “Var ya yox?”
Set-lər (HashSet<T>) “var ya yox” tipli axtarış üçün yaradılıb. İndeksə görə axtarış yoxdur, amma mövcudluğu çox tez yoxlayır:
HashSet<int> set = new HashSet<int> { 1, 3, 5, 7 };
bool hasThree = set.Contains(3); // True
Console.WriteLine(hasThree);
// Şərtə görə axtarış lazımdırsa (məsələn, cüt ədəd varmı?):
bool hasEven = false;
foreach (var x in set)
{
if (x % 2 == 0)
{
hasEven = true;
break;
}
}
Console.WriteLine(hasEven); // False
6. Dictionary-də axtarış: Dictionary<TKey, TValue>
Dictionary — “açar-dəyər” cütləri kolleksiyasıdır. Açarla axtarış — onun super gücüdür.
Açarın mövcudluğunu yoxlamaq
Dictionary<int, string> idToName = new Dictionary<int, string>
{
{ 1, "Vasya" }, { 2, "Katya" }
};
if (idToName.ContainsKey(2))
Console.WriteLine(idToName[2]); // "Katya"
Açarla dəyəri tapmaq: təhlükəsiz!
if (idToName.TryGetValue(3, out string result))
Console.WriteLine(result);
else
Console.WriteLine("Bu Id-li tələbə yoxdur"); // Bunu çıxaracaq
Dəyərə görə axtarış (nadir və yavaşdır):
bool containsVasya = idToName.ContainsValue("Vasya");
Console.WriteLine(containsVasya); // True
Dəyərə və ya açara görə şərtlə tapmaq
// Adı "K" ilə başlayan ilk Id
KeyValuePair<int, string> entry = default;
bool found = false;
foreach (var pair in idToName)
{
if (pair.Value.StartsWith("K"))
{
entry = pair;
found = true;
break;
}
}
if (found)
Console.WriteLine($"{entry.Key}: {entry.Value}"); // "2: Katya"
7. Faydalı nüanslar
Axtarış metodları cədvəli
| Kolleksiya tipi | Mövcudluğu yoxla Contains | İndeksi tap IndexOf | Şərtlə tap Find | Təhlükəsiz açarla axtarış TryGetValue |
|---|---|---|---|---|
|
Bəli | Bəli | Bəli () |
- |
(massiv) |
Bəli (/dövr) |
Bəli () |
Dövr | - |
|
Bəli | - | Yox (yalnız əl ilə) | - |
|
Bəli () |
- | Əl ilə açar/dəyərə görə | Bəli |
İterativ axtarış: özümüz yazırıq
Tam başa düşmək üçün kolleksiya üçün axtarış metodunu özümüz yazaq. Məsələn, verilmiş dəyərdən böyük ilk elementin indeksini tapmaq:
static int FindFirstGreaterIndex(IEnumerable<int> collection, int minValue)
{
int index = 0;
foreach (var item in collection)
{
if (item > minValue)
return index;
index++;
}
return -1; // tapılmadı
}
var nums = new List<int> { 1, 4, 7, 2 };
Console.WriteLine(FindFirstGreaterIndex(nums, 3)); // 1 (4 rəqəmi)
Burada biz nə tipə (List<T>, int[], hətta HashSet<T>) nə də daxili implementasiyaya bağlı deyilik.
Axtarışın real tapşırıqlarda tətbiqi
- Verilənlər bazasında login və ya e-mail ilə istifadəçi axtarışı.
- Səbətdə bu məhsulun olub-olmadığını yoxlamaq.
- Parametr adını görə ayarların tez axtarışı.
- Müəyyən addımın artıq yerinə yetirilib-yetirilmədiyini yoxlamaq (məsələn, workflow-da).
- Log massivində səhvin yerini tapmaq.
Middle-developer müsahibələrinin çoxunda mütləq belə sual olur: “Kolleksiyada elementləri necə axtarırsan? Şərtə görə ilk/bütün/indeks qaytaran metodu necə yazardın?”. Yəni axtarış praktikasını öyrənmək çox faydalıdır!
8. Axtarışda tipik səhvlər və xüsusiyyətlər
Vacib məqam: axtarış metodları obyektlərin necə müqayisə olunmasından asılıdır. Məsələn, siyahıya öz class-larını əlavə etsən, default müqayisə — referans müqayisəsidir! Axtarışın “məzmun”a görə işləməsi üçün Equals və GetHashCode metodlarını override etmək lazımdır (bunun haqqında növbəti mühazirələrdə daha ətraflı).
Problem nümunəsi:
var s1 = new Student { Name = "Eqor", Id = 42 };
students.Add(s1);
// İndi eyni Id və adla yeni obyekt yaradırıq:
var s2 = new Student { Name = "Eqor", Id = 42 };
Console.WriteLine(students.Contains(s2)); // False (!)
Kompilyator sahələrə görə yox, referansa görə müqayisə edir (bunlar fərqli obyektlərdir).
GO TO FULL VERSION