آرایه های چند بعدی

آرایه‌های چند بعدی آرایه‌هایی هستند که برای دسترسی به هر یک از عناصر آنها باید از چندین اندیس استفاده کنیم. یک آرایه چند بعدی را می‌توان مانند یک جدول با تعدای ستون و ردیف تصور کنید. با افزایش اندیسها اندازه ابعاد آرایه نیز افزایش می‌یابد و آرایه‌های چند بعدی با بیش از دو اندیس به وجود می‌آیند. نحوه ایجاد یک آرایه با دو بعد به صورت زیر است :

datatype[,] arrayName = new datatype[lengthX, lengthY];

و یک آرایه سه بعدی به صورت زیر ایجاد می‌شود :

datatype[, ,] arrayName = new datatype[lengthX, lengthY, lengthZ];

می‌توان یک آرایه با تعداد زیادی بعد ایجاد کرد به شرطی که هر بعد دارای طول مشخصی باشد. به دلیل اینکه آرایه‌های سه بعدی یا آرایه‌های با بیشتر از دو بعد بسیار کمتر مورد استفاده قرار می‌گیرند اجازه بدهید که در این درس بر روی آرایه‌های دو بعدی تمرکز کنیم. در تعریف این نوع آرایه ابتدا نوع آرایه یعنی اینکه آرایه چه نوعی از انواع داده را در خود ذخیره می‌کند را مشخص می‌کنیم. سپس یک جفت کروشه و در داخل کروشه‌ها یک کاما قرار می‌دهیم. به تعداد کاماهایی که در داخل کروشه می‌گذارید توجه کنید. اگر آرایه ما دو بعدی است باید 1 کاما و اگر سه بعدی است باید 2 کاما قرار دهیم. سپس یک نام برای آرایه انتخاب کرده و بعد تعریف آنرا با گذاشتن کلمه new ، نوع داده و طول آن کامل می‌کنیم. در یک آرایه دو بعدی برای دسترسی به هر یک از عناصر به دو مقدار نیاز داریم یکی مقدار X و دیگری مقدار Y که مقدار x نشان دهنده ردیف و مقدار Y نشان دهنده ستون آرایه است البته اگر ما آرایه دو بعدی را به صورت جدول در نظر بگیریم. یک آرایه سه بعدی را می‌توان به صورت یک مکعب تصور کرد که دارای سه بعد است و x طول، Y عرض و z ارتفاع آن است. یک مثال از آرایه دو بعدی در زیر آمده است :

int[,] numbers = new int[3, 5];

کد بالا به کامپایلر می‌گوید که فضای کافی به عناصر آرایه اختصاص بده (در این مثال 15 خانه). در شکل زیر مکان هر عنصر در یک آرایه دو بعدی نشان داده شده است.
multidimentional-arrays-12-13-10-01
مقدار 3 را به x اختصاص می‌دهیم چون 3 سطر و مقدار 5 را به Y چون 5 ستون داریم اختصاص می‌دهیم. چطور یک آرایه چند بعدی را مقدار دهی کنیم؟ چند راه برای مقدار دهی به آرایه‌ها وجود دارد.

datatype[,] arrayName = new datatype[x, y] { { r0c0, r0c1, ... r0cX },
                                             { r1c0, r1c1, ... r1cX },
                                                       .
                                                       .
                                                       .
                                             { rYc0, rYc1, ... rYcX } };

برای راحتی کار می‌توان از نوشتن قسمت new dataype[,] صرف نظر کرد.

datatype[,] arrayName = { { r0c0, r0c1, ... r0cX },
                          { r1c0, r1c1, ... r1cX },
                                   .
                                   .
                                   .
                          { rYc0, rYc1, ... rYcX } };

به عنوان مثال :

 int[,] numbers = { { 1, 2, 3, 4, 5 },
                   { 6, 7, 8, 9, 10 },
                   { 11, 12, 13, 14, 15 } };

و یا می‌توان مقدار دهی به عناصر را به صورت دستی انجام داد مانند :

array[0, 0] = value;
array[0, 1] = value;
array[0, 2] = value;
array[1, 0] = value;
array[1, 1] = value;
array[1, 2] = value;
array[2, 0] = value;
array[2, 1] = value;
array[2, 2] = value;

همانطور که مشاهده می‌کنید برای دسترسی به هر یک از عناصر در یک آرایه دو بعدی به سادگی می‌توان از اندیسهای X و Y و یک جفت کروشه مانند مثال استفاده کرد.

گردش در میان عناصر آرایه‌های چند بعدی

گردش در میان عناصر آرایه‌های چند بعدی نیاز به کمی دقت دارد. یکی از راههای آسان استفاده از حلقه foreach و یا حلقه for تو در تو است. اجازه دهید ابتدا از حلقه foreach استفاده کنیم.

   1: using System;
   2: 
   3: public class Program
   4: {
   5:     public static void Main()
   6:     {
   7:         int[,] numbers = { { 1, 2, 3, 4, 5 },
   8:                            { 6, 7, 8, 9, 10 },
   9:                            { 11, 12, 13, 14, 15 }
  10:                          };
  11: 
  12:         foreach (int number in numbers)
  13:         {
  14:             Console.Write(number + " ");
  15:         }
  16:     }
  17: }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

مشاهده کردید که گردش در میان مقادیر عناصر یک آرایه چند بعدی چقدر راحت است. به وسیله حلقه foreach نمی‌توانیم انتهای ردیفها را مشخص کنیم. برنامه زیر نشان می‌دهد که چطور از حلقه for برای خواندن همه مقادیر آرایه و تعیین انتهای ردیف‌ها استفاده کنید.

   1: using System;
   2: 
   3: public class Program
   4: {
   5:     public static void Main()
   6:     {
   7:         int[,] numbers = { { 1, 2, 3, 4, 5 },
   8:                            { 6, 7, 8, 9, 10 },
   9:                            { 11, 12, 13, 14, 15 }
  10:                          };
  11: 
  12:         for (int row = 0; row < numbers.GetLength(0); row++)
  13:         {
  14:             for (int col = 0; col < numbers.GetLength(1); col++)
  15:             {
  16:                 Console.Write(numbers[row, col] + " ");
  17:             }
  18: 
  19:             //Go to the next line
  20:             Console.WriteLine();
  21:         }
  22:     }
  23: }
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15

همانطور که در مثال بالا نشان داده شده است با استفاده از یک حلقه for نمی‌توان به مقادیر دسترسی یافت بلکه به یک حلقه for تو در تو نیاز داریم، زیرا آرایه دو بعدی به صورت یک جدول شامل سطر و ستون است، پس لازم است که از یک حلقه for برای گردش در میان سطرها و از حلقه for دیگر برای گردش در میان ستون‌های این جدول (آرایه) استفاده کنیم.
اولین حلقه for (خط 12) برای گردش در میان ردیف‌های آرایه به کار می‌رود. این حلقه تا زمانی ادامه می‌یابد که مقدار ردیف کمتر از طول اولین بعد باشد (زیرا اندیس ابعاد آرایه از صفر شروع می‌شود. در مثال بالا مقدار اولین بعد برابر 3 است). در این مثال از متد GetLength() کلاس Array استفاده کرده‌ایم. این متد طول آرایه را در یک بعد خاص نشان می‌دهد و دارای یک پارامتر است که همان بعد آرایه می‌باشد. به عنوان مثال برای به دست آوردن طول اولین بعد آرایه مقدار صفر را به این متد ارسال می‌کنیم چون اندیس ابعاد آرایه از صفر شروع می‌شود.

در داخل اولین حلقه for حلقه for دیگری تعریف شده است (خط 14). در این حلقه یک شمارنده برای شمارش تعداد ستونهای (col) هر ردیف تعریف شده است و در شرط داخل آن بار دیگر از متد GetLength() استفاده شده است، ولی این بار مقدار 1 را به آن ارسال می‌کنیم تا طول بعد دوم آرایه را به دست آوریم. پس به عنوان مثال وقتی که مقدار ردیف (row) صفر باشد، حلقه دوم از [0, 0] تا [0, 4] اجرا می‌شود. سپس مقدار هر عنصر از آرایه را با استفاده از حلقه نشان می‌دهیم، اگر مقدار ردیف(row) برابر 0 و مقدار ستون (col) برابر 0 باشد مقدار عنصری که در ستون 1 و ردیف 1 (numbers[0, 0]) قرار دارد نشان داده خواهد شد که در مثال بالا عدد 1 است.

بعد از اینکه دومین حلقه تکرار به پایان رسید، فوراً دستورات بعد از آن اجرا خواهند شد، که در اینجا دستور Console.WriteLine() که به برنامه اطلاع می‌دهد که به خط بعد برود. سپس حلقه با اضافه کردن یک واحد به مقدار row این فرایند را دوباره تکرار می‌کند. سپس دومین حلقه for اجرا شده و مقادیر دومین ردیف نمایش داده می‌شود. این فرایند تا زمانی اجرا می‌شود که مقدار row کمتر از طول اولین بعد باشد. حال بیایید آنچه را از قبل یاد گرفته‌ایم در یک برنامه به کار بریم. این برنامه نمره چهار درس مربوط به سه دانش آموز را از ما می‌گیرد و معدل سه دانش آموز را حساب می‌کند.

   1: using System;
   2: 
   3: public class Program
   4: {
   5:     public static void Main()
   6:     {
   7:         double[,] studentGrades = new double[3, 4];
   8:         double total;
   9: 
  10:         for (int student = 0; student < studentGrades.GetLength(0); student++)
  11:         {
  12:             total = 0;
  13: 
  14:             Console.WriteLine("Enter grades for Student {0}", student + 1);
  15: 
  16:             for (int grade = 0; grade < studentGrades.GetLength(1); grade++)
  17:             {
  18:                 Console.Write("Enter Grade #{0}: ", grade + 1);
  19:                 studentGrades[student, grade] = Convert.ToDouble(Console.ReadLine());
  20:                 total += studentGrades[student, grade];
  21:             }
  22: 
  23:             Console.WriteLine("Average is {0:F2}",
  24:                                (total / studentGrades.GetLength(1)));
  25:             Console.WriteLine();
  26:         }
  27: 
  28:     }
  29: }
Enter grades for Student 1
Enter Grade #1: 92
Enter Grade #2: 87
Enter Grade #3: 89
Enter Grade #4: 95
Average is 90.75

Enter grades for Student 2
Enter Grade #1: 85
Enter Grade #2: 85
Enter Grade #3: 86
Enter Grade #4: 87
Average is 85.75

Enter grades for Student 3
Enter Grade #1: 90
Enter Grade #2: 90
Enter Grade #3: 90
Enter Grade #4: 90
Average is 90.00

در برنامه بالا یک آرایه چند بعدی از نوع double تعریف شده است (خط 7). همچنین یک متغیر به نام total تعریف می‌کنیم که جمع نمرات وارد شده برای دانش آموز در آن قرار می‌گیرد. حال وارد حلقه for تو در تو می‌شویم (خط 10). در اولین حلقه for یک متغیر به نام student تعریف کرده‌ایم که مقادیر اولین بعد آرایه (که همان تعداد دانش آموزان است) در آن قرار می‌گیرد. از متد GetLength() هم برای تشخیص تعداد دانش آموزان استفاده شده است. وارد بدنه حلقه for می‌شویم. در خط 12 مقدار متغیر total را برابر صفر قرار می‌دهیم. سپس برنامه یک پیغام را نشان می‌دهد و از شما می‌خواهد که نمرات دانش آموز را وارد کنید (student + 1). عدد 1 را به student اضافه کرده‌ایم تا به جای نمایش Student 0، با Student 1 شروع شود، تا طبیعی‌تر به نظر برسد. سپس به دومین حلقه for در خط 16 می‌رسیم. وظیفه این حلقه گردش در میان دومین بعد که همان نمرات دانش آموز است می‌باشد. برنامه چهار نمره مربوط به دانش آموز را می‌گیرد. هر وقت که برنامه یک نمره را از کاربر دریافت می‌کند، نمره به متغیر total اضافه می‌شود.

وقتی همه نمره‌ها وارد شدند، متغیر total هم جمع همه نمرات را نشان می‌دهد. در خطوط 24-23 معدل دانش آموز نشان داده می‌شود. به فرمت {0:F2} توجه کنید. این فرمت معدل را تا دو رقم اعشار نشان می‌دهد. معدل از تقسیم کردن total (جمع) بر تعداد نمرات به دست می‌آید. از متد GetLength(1) هم برای به دست آوردن تعداد نمرات استفاده می‌شود.