CodeGym /Kurslar /C# SELF /Massivlərlə qabaqcıl işləmə

Massivlərlə qabaqcıl işləmə

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

1. string tipli massiv

Qısaca olaraq, string tipli massiv haqqında danışmaq istəyirəm.

Artıq dediyimiz kimi, massiv istənilən tipdə ola bilər. Yəni, string tipli massiv də yarada bilərik. Gəlin baxaq, əgər bizə belə bir proqram yazmaq lazım olsaydı ki, “klaviaturadan 10 sətir daxil edir və onları əks ardıcıllıqla ekrana çıxarır”, kod necə olardı:

string[] array = new string[10];	// 10 elementlik massiv-obyekt yaradırıq
for (int i = 0; i < 10; i++)		// 0-dan 9-a qədər dövr
{
   array[i] = Console.ReadLine();	// Klaviaturadan sətir oxuyuruq və massivə yazırıq
}
for (int i = 9; i >= 0; i--)		// 9-dan 0-a qədər dövr
{
    Console.WriteLine(array[i]);	// Massivin növbəti elementini ekrana çıxarırıq
}

Kod demək olar ki, dəyişməyib! Sadəcə massiv yaradanda int tipini string ilə əvəz etdik. Qalan hər şey tam eynidir!

2. string tipli massiv yaddaşda

Bir faydalı fakt da var. 3 şəkilə baxaq:

Şəkil 1. string obyekti yaddaşda necə yerləşir:

Yaddaşda string tipli massiv

Diqqət et, sətirin mətni birbaşa dəyişəndə saxlanmır: onun üçün ayrıca yaddaş bloku ayrılır. string tipli dəyişəndə isə mətn obyektinin ünvanı (referansı) saxlanılır.

Şəkil 2. Tam ədədlər massivinin yaddaşda yerləşməsi:

int array in memory

Bu şəkli də artıq görmüsən.

Şəkil 3. Yaddaşda string massiv necə yerləşir:

How a string array is stored in memory

Solda string[] tipli massiv-dəyişəni görürük (massiv-obyektin ünvanını saxlayır).
Ortada — string tipli massiv-obyekt.
Sağda isə — mətn saxlayan string-obyektlər.

string tipli massiv-obyektin hüceyrələrində mətnlər (string-lər) yox, onların ünvanları (referansları) saxlanılır. Eynilə string tipli dəyişənlərdə də mətnin ünvanı saxlanılır.

3. C#-da massivlərin tez initialize olunması

Massivlər — çox faydalı şeydir, ona görə də C# developer-ləri onlarla işi maksimum rahat etməyə çalışıblar. Və ilk etdikləri şey — massivin initialize olunmasını sadələşdirmək olub, yəni ilkin dəyərləri ora yazmaq.

Çox vaxt, proqramın haradansa oxuduğu datalardan əlavə, ona öz daxili dataları da lazımdır. Məsələn, bütün ayların uzunluğunu massivdə saxlamaq lazımdır. Bu kod necə görünə bilər:

int[] months = new int[12];
months[0] = 31; // yanvar
months[1] = 28; // fevral
months[2] = 31; // mart
months[3] = 30; // aprel
months[4] = 31; // may
months[5] = 30; // iyun
months[6] = 31; // iyul
months[7] = 31; // avqust
months[8] = 30; // sentyabr
months[9] = 31; // oktyabr
months[10] = 30; // noyabr
months[11] = 31; // dekabr

Amma bunu daha qısa yazmaq olar — C# yaradıcılarına təşəkkür:

// ilin aylarının uzunluqları
int[] months = new int[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

Sadəcə bütün massiv elementlərini vergüllə ayırıb yaza bilərsən!

Rahatdır, düzdür? Amma hələ bu da hamısı deyil.

Məlum olur ki, compiler massiv-dəyişənin tipinə baxıb massiv-obyektin tipini özü müəyyən edə bilir. Uzunluğunu isə — sadəcə mötərizədə neçə element varsa, sayır.

Ona görə bu kodu daha da qısa yaza bilərsən:

// ilin aylarının uzunluqları
int[] months = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

Əla deyil? 🙂

Bu yazılışa “massivin tez initialize olunması” deyirlər. Bu, təkcə int üçün yox, başqa tiplər üçün də işləyir...

// ilin aylarının adları
string[] months = { "Yanvar", "Fevral", "Mart", "Aprel", "May", "Iyun", "Iyul", "Avqust", "Sentyabr", "Oktyabr", "Noyabr", "Dekabr"};

4. foreach dövrü

Massivin bütün elementlərini gəzmək o qədər tez-tez lazım olur ki, bunun üçün ayrıca dövr icad ediblər(!). Onun adı foreach-dir. Yazılışı belədir:


foreach (int score in scores)
{
    Console.WriteLine($"Ballar: {score}");
}
        
Massivin elementlərini foreach ilə gəzmək

Burada dövr özü elementləri gəzib keçir ― heç bir əl ilə indeks yoxdur. Elementləri birbaşa dəyişmək olmaz (dövr daxilində onlar yalnız oxumaq üçün açıqdır), amma sadəcə “gəzib keçmək” üçün çox rahatdır.

Compiler foreach dövrünü aşağıdakı koda çevirəcək:


for (int i = 0; i < scores.Length; i++)
{
    int score = scores[i];
    Console.WriteLine($"Ballar: {score}");
}
        
foreach “arxa planda” necə işləyir

Yəni heç bir magiya yoxdur. İndi başa düşmək asandır ki, niyə score dəyişəni ilə massiv elementlərini dəyişə bilmirsən.

Gəlin bir nümunə də yazaq: bütün balların cəmini tapaq.


int sum = 0;
foreach (int score in scores)
{
    sum += score;
}
Console.WriteLine($"Bütün balların cəmi: {sum}");
        
foreach ilə massiv elementlərinin cəmlənməsi

Hansını nə vaxt istifadə etməli?

  • Əgər indeks lazımdırsa və ya elementləri dəyişmək istəyirsənsə — for dövrü.
  • Sadəcə dəyərləri gəzmək üçün — foreach daha tez və təmizdir.

5. Sondan indeksləşdirmə: ^ operatoru

Artıq C#-da massivdən elementləri sondan almaq olur. Əvvəllər necə idi, sonuncu elementi almaq üçün belə yazırdın:


int lastScore = scores[scores.Length - 1];
        
Köhnə üsulla massivdən sonuncu elementi almaq

İndi isə hər şey daha rahatdır. Sadəcə indeksdən əvvəl ^ yazırsan və sayma sondan başlayır:


int lastScore = scores[^1];        // Sonuncu element
int penultimate = scores[^2];      // Sonuncudan əvvəlki element
        
^ ilə sondan indeksləşdirmə
  • ^1 — sondan birinci (yəni sonuncu).
  • ^2 — sondan ikinci.

Vizualizasiya

İndeks scores massivindəki dəyər Adi indeks Sondan indeks
0 10 0 ^5
1 15 1 ^4
2 8 2 ^3
3 22 3 ^2
4 17 4 ^1

score[^1] = 17, score[^2] = 22 — rahat və aydındır.

Vacib! Diqqət et, sondan indekslər 1-dən başlayır, 0-dan yox.

6. Diapazonlar: .. (range) operatoru

Bəzən əsas massivdən alt-massiv almaq lazımdır. C#-da bunun üçün xüsusi diapazon operatoru .. var — bu, massivdən istədiyin “parçanı” almaq üçün qısa və rahat üsuldur.

Belə alt-massivə bəzən slice (ingiliscə “slice”) deyirlər və o, iki sərhədlə müəyyən olunur: başlanğıc və son.
Vacib məqam: sağ sərhəd nəticəyə daxil olmur!

Necə görünür


int[] scores = { 10, 15, 8, 22, 17 };
int[] top3 = scores[0..3]; // 0-dan 2-yə qədər elementlər: {10, 15, 8}
        
.. ilə massivdən slice almaq

  • scores[0..3] — 0-cı indeksdən (daxil olmaqla) 3-cü indeksə (DAHİL OLMADAN) qədər elementləri alırıq.
  • Nəticə massivdə 0, 1 və 2 indeksli elementlər olacaq.

Qısaltmalar

Əgər sol sərhəd göstərilməyibsə, ən başdan başlayırıq:


int[] firstTwo = scores[..2]; // scores[0..2] ilə eyni, yəni {10, 15}
        

Əgər sağ sərhəd göstərilməyibsə, sona qədər alırıq:


int[] fromThird = scores[2..]; // {8, 22, 17}
        

Mənfi indekslər

^ simvolu ilə sondan indeksləri saymaq olar:


int[] lastTwo = scores[^2..]; // {22, 17}
        

Burada ^2 — “sondan ikinci element” deməkdir.

Həmçinin, hər iki tərəfdə mənfi indekslərdən istifadə edərək “aralıq” diapazon da götürmək olar:


int[] mid = scores[1..^1]; // {15, 8, 22} (2-ci elementdən sonuncudan əvvəlkinə qədər)
        

Nələri yadda saxlamaq lazımdır

  • Sağ sərhəd həmişə daxil olmur — yəni a..b yazanda, a-dan b-1-ə qədər bütün elementləri alırsan.
  • Əgər sərhədlər massivdən kənara çıxsa, IndexOutOfRangeException atılacaq.
  • Slice — yeni massivdir, orijinal dəyişmir. Yeni massivdə etdiyin dəyişikliklər əsas massivə təsir etmir.

Praktik nümunələr

int[] arr = { 1, 2, 3, 4, 5, 6, 7 };
int[] arr = { 1, 2, 3, 4, 5, 6, 7 };

int[] start = arr[..3];      // {1, 2, 3}
int[] end = arr[^2..];       // {6, 7}
int[] middle = arr[2..5];    // {3, 4, 5}
int[] all = arr[..];         // {1, 2, 3, 4, 5, 6, 7} (tam surət)
2
Tapşırıq
C# SELF, səviyyə, dərs
Bağlanıb
Sondan indeksləmə və diapazonlardan istifadə
Sondan indeksləmə və diapazonlardan istifadə
2
Tapşırıq
C# SELF, səviyyə, dərs
Bağlanıb
Sətir massivinin tərsi və kəsikləri
Sətir massivinin tərsi və kəsikləri
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION