CodeGym /Kurslar /C# SELF /C# kolleksiyalarında elementlərin axtarışı

C# kolleksiyalarında elementlərin axtarışı

C# SELF
Səviyyə , Dərs
Mövcuddur

1. Kolleksiyalarda axtarışın əsas imkanları

Çox vaxt “axtarış”“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
List<T>
Contains
IndexOf
Find
-
T[]
(massiv)
Contains
/
Array.IndexOf
Array.IndexOf
- -
HashSet<T>
Contains
- - -
Dictionary<TKey,V>
ContainsKey
,
ContainsValue
- - İndeksatoru var
[key]

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
List<T>
Bəli Bəli Bəli (
Find
)
-
T[]
(massiv)
Bəli (
Array.Contains
/dövr)
Bəli (
Array.IndexOf
)
Dövr -
HashSet<T>
Bəli - Yox (yalnız əl ilə) -
Dictionary<TKey,V>
Bəli (
ContainsKey
)
- Ə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 EqualsGetHashCode 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).

Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION