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

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

var arrayName [row] [column] dataType

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

var arrayName [row] [column] [height] dataType

به دلیل اینکه آرایه‌های سه بعدی یا آرایه‌های با بیشتر از دو بعد بسیار کمتر مورد استفاده قرار می‌گیرند اجازه بدهید که در این درس بر روی آرایه‌های دو بعدی تمرکز کنیم. اگر آرایه دو بعدی را یک مربع یا مستطیل فرض کنیم، در تعریف این نوع آرایه ابتدا نام آرایه، سپس تعداد سطر (row) و ستون های (column) آن و در آخر نوع داده آرایه (dataType) را مشخص می کنیم. در یک آرایه دو بعدی برای دسترسی به هر یک از عناصر به دو مقدار نیاز داریم یکی مقدار X و دیگری مقدار Y که مقدار x نشان دهنده ردیف و مقدار Y نشان دهنده ستون آرایه است البته اگر ما آرایه دو بعدی را به صورت جدول در نظر بگیریم. یک آرایه سه بعدی را می‌توان به صورت یک مکعب تصور کرد که دارای سه بعد است و x طول، Y عرض و z ارتفاع آن است. یک مثال از آرایه دو بعدی در زیر آمده است :

var numbers [3][5] int

کد بالا به کامپایلر می‌گوید که فضای کافی به عناصر آرایه اختصاص بده (در این مثال 15 خانه). در شکل زیر مکان هر عنصر در یک آرایه دو بعدی نشان داده شده است.

مقدار 3 را به x اختصاص می‌دهیم چون 3 سطر و مقدار 5 را به Y چون 5 ستون داریم اختصاص می‌دهیم. چطور یک آرایه چند بعدی را مقدار دهی کنیم؟ چند راه برای مقدار دهی به آرایه‌ها وجود دارد. یک راه این است که مقادیر عناصر آرایه را در همان زمان تعریف آرایه، مشخص کنیم :

var numbers = [3][5] int{
    { 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 و یک جفت کروشه مانند مثال استفاده کرد.

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

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

  1: package main
  2: 
  3: import "fmt"
  4: 
  5: func main() {
  6:   
  7:     var row, column int
  8:     var numbers = [3][5] int{
  9:         { 1, 2, 3, 4, 5      },
 10:         { 6, 7, 8, 9, 10     },
 11:         { 11, 12, 13, 14, 15 },
 12:     }
 13: 
 14:     for row=0; row<len(numbers); row++ {
 15:         for column=0; column<len(numbers[0]); column++ {
 16:             fmt.Printf("%d  ", numbers[row][column])
 17:         }
 18:         fmt.Println()
 19:     }
 20: }
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15

همانطور که در مثال بالا نشان داده شده است با استفاده از یک حلقه ساده for نمی‌توان به تمامی مقادیر دسترسی یافت بلکه، به یک حلقه for تو در تو نیاز داریم. در اولین حلقه for (خط 14) یک متغیر تعریف شده است که در میان ردیف‌های آرایه (row) گردش می‌کند. این حلقه تا زمانی ادامه می‌یابد که مقدار ردیف کمتر از طول اولین بعد باشد. در این مثال از متد ()len استفاده کرده‌ایم. این متد طول آرایه را در یک بعد خاص نشان می‌دهد. به عنوان مثال برای به دست آوردن طول اولین بعد آرایه که همان تعداد ردیف‌ها می‌باشد از دستور len(numbers) استفاده کرده‌ایم.

در داخل اولین حلقه for حلقه for دیگری تعریف شده است (خط 15). در این حلقه یک شمارنده برای شمارش تعداد ستونهای (columns) هر ردیف تعریف شده است و در شرط داخل آن بار دیگر از متد ()len استفاده شده است، ولی این بار به نوعی دیگر و به صورت زیر از آن استفاده کرده ایم:

len(numbers[column])

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

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

  1: package main
  2: 
  3: import "fmt"
  4: 
  5: func main() {
  6: 
  7:     var student, grade       int
  8:     var studentGrades [3][4] float32
  9:     var total                float32
 10: 
 11:     for student = 0; student < len(studentGrades); student++ {
 12:         total = 0
 13:         fmt.Printf("\nEnter grades for Student %d \n", student+1)
 14: 
 15:         for grade = 0; grade < len(studentGrades[grade]); grade++ {
 16:             fmt.Printf("Enter Grade #%d: ", grade+1)
 17:             fmt.Scanln(&studentGrades[student][grade])
 18:             total += studentGrades[student][grade]
 19:         }
 20: 
 21:         fmt.Printf("Average is %.2f", (total / float32(len(studentGrades[student]))))
 22:         fmt.Println();
 23:     }
 24: }
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

در برنامه بالا یک آرایه چند بعدی از نوع float32 تعریف شده است (خط 8). همچنین یک متغیر به نام total تعریف می‌کنیم که مقدار محاسبه شده معدل هر دانش آموز را در آن قرار دهیم. حال وارد حلقه for تو در تو می‌شویم (خط 11). در اولین حلقه for یک متغیر به نام sudent برای تشخیص پایه درسی هر دانش آموز تعریف کرده‌ایم. از متد ()len هم برای تشخیص تعداد دانش آموزان استفاده شده است. وارد بدنه حلقه for می‌شویم. در خط 12 مقدار متغیر total را برابر صفر قرار می‌دهیم. بعداً مشاهده می‌کنید که چرا این کار را انجام دادیم. سپس برنامه یک پیغام را نشان می‌دهد و از شما می‌خواهد که شماره دانش آموز را وارد کنید (student + 1). عدد 1 را به student اضافه کرده‌ایم تا به جای نمایش Student 0، با Student 1 شروع شود، تا طبیعی‌تر به نظر برسد. سپس به دومین حلقه for در خط 15 می‌رسیم. در این حلقه یک متغیر شمارنده به نام grade تعریف می‌کنیم که طول دومین بعد آرایه را با استفاده از len(studentGrades[grade]) به دست می‌آورد. این طول تعداد نمراتی را که برنامه از سؤال می‌کند را نشان می‌دهد. برنامه چهار نمره مربوط به دانش آموز را می‌گیرد. هر وقت که برنامه یک نمره را از کاربر دریافت می‌کند، نمره به متغیر total اضافه می‌شود.

وقتی همه نمره‌ها وارد شدند، متغیر total هم جمع همه نمرات را نشان می‌دهد. در خط 21 معدل دانش آموز نشان داده می‌شود. معدل از تقسیم کردن total (جمع) بر تعداد نمرات به دست می‌آید. از len(studentGrades[student]) هم برای به دست آوردن تعداد نمرات استفاده می‌شود.