آرایه ها در زبان برنامه نویسی سوئیفت (Swift) – به زبان ساده


در این مقاله به بررسی ساختمان داده و الگوریتمهای مختلفی که در زبان برنامه نویسی سوئیفت وجود دارند میپردازیم و بیشترین تمرکز ما روی آرایهها خواهد بود.
ساختمان داده چیست؟
ساختمانهای داده بلوکهای سازندهای هستند که برای ساخت یک سیستم مورد استفاده قرار میگیرند. این بلوکها امکان توسعه سیستمهای مؤثر، مقیاسپذیر، و قابل نگهداری را فراهم میسازند. آنها همچنین ابزاری برای سازماندهی و ارائه دادهها در مواردی که لازم است بین موجودیتهای مختلف به اشتراک درآیند، ارائه میکنند. ساختمانهای داده نهتنها موجب سهولت فرایند اشتراک دادهها میشوند، بلکه نگهداری، مرتبسازی و جستجوی دادهها را نیز آسانتر میسازند.
همه اپلیکیشنهای نرمافزاری، صرفنظر از سیستمی که برای توسعه آنها استفاده میشود، بر مبنای داده ساخته شدهاند. در توسعه اغلب اپلیکیشنهای مدرن از «رابطهای برنامهنویسی اپلیکیشن» (API) برای کمک به ایجاد محصولهای شگفتانگیز استفاده میشود؛ با این وجود API ها هم از ساختمان و الگوریتم دادهها استفاده میکنند.
دو ساختمان داده بنیادی وجود دارند که برای توسعه هر نرمافزاری ضروری محسوب میشوند: آرایهها و لیستهای پیوندی. این ساختمانهای داده برای ایجاد ساختمانهای داده پیشرفتهتر ضروری هستند. در این مقاله در مورد آرایهها صحبت خواهیم کرد.
آرایه چیست؟
آرایه مجموعه مرتب و با دسترسی تصادفی است که به صورتی پیوسته دادهها را در بلوکهای مجاوری از حافظه ذخیره میسازد. آرایه یکی از شناختهشدهترین ساختمانهای داده محسوب میشود و در اغلب زبانهای برنامهنویسی مورد استفاده قرار میگیرد. آرایه یکبُعدی با استفاده از نمادگذاری ریاضیاتی به صورت زیر نمایش مییابد:

که a0 نماینده عنصر نخست آرایه و ai نماینده عنصر i+1-ام آرایه است.
نوع دیگری از آرایه به نام آرایه چندبُعدی نیز وجود دارد. یک ماتریس چندبُعدی به صوت آرایه چندبُعدی پیادهسازی میشود. در مثال زیر یک ماتریس دوبُعدی به تصویر درآمده است که به صورت یک آرایه دوبُعدی عمل میکند.

a00 نماینده عنصر ردیف نخست و ستون نخست است. به طور مشابه aij نماینده عنصر ردیف i و ستون j است.
در سوئیفت سه روش برای اعلان و مقداردهی اولیه یک آرایه وجود دارد:
- شکل کامل که از نمادگذاری <Array<ElementType استفاده میکند.
- شکل خلاصه که از نمادگذاری [ElementType] استفاده میکند.
- استنباط نوع (Type inference).
میتوان از شکل کامل به صورت زیر برای اعلان یک آرایه استفاده کرد:
var arrayOfInts: Array<Int> = [1، 2، 3، 4، 5، 6]
در این بخش ما یک آرایه به نام arrayOfInts را اعلان و مقداردهی اولیه کردهایم که شامل نوع Int است و عنصر اول آرایه برابر با 1 و عنصر آخر 6 است. ما میتوانیم از اندیسگذاری آرایه برای دسترسی به هر یک از عناصر آن استفاده کنیم. به خاطر داشته باشید که اندیس آرایهها در سوئیفت از صفر آغاز میشود و عنصر آخر آرایه فوق در اندیس 5 قرار دارد:
arrayOfInts[5]
برای اعلان یک آرایه با استفاده از نمادگذاری خلاصه به صورت زیر عمل میکنیم:
var arrayOfInts: [Int] = [1، 2، 3، 4، 5، 6]
در نهایت برای اعلان یک آرایه با استفاده از استنباط نوع باید به صورت زیر عمل کنیم:
var arrayOfInts = [1، 2، 3، 4، 5، 6]
استنباط نوع در بخش کامپایلر سوئیفت اجرا میشود و نوع عناصر بر مبنای مقدار ارائه شده در زمان کامپایل تعیین میشود.
در سوئیفت نمادگذاری خلاصه نهتنها روشی ترجیحی برای اعلان یک آرایه محسوب میشود؛ بلکه از سوی اپل نیز توصیه میشود. استنباط نوع با این که در عمل جواب میدهد؛ اما با ریسک همراه است، چون سوئیفت در برخی مواد نمیتواند نوع صحیح مقدارها را تعیین کند. برای مثال در کد زیر:
var arrayOfFloats = [1.1، 1.2، 1.3، 1.4]
با این که قصد برنامهنویس اعلان و مقداردهی آرایهای از نوع Float بوده است؛ اما استنباط نوع سوئیفت یک آرایه arrayOfFloats به صورت Double را اعلان و مقداردهی اولیه میکند.
مزیت دیگر «فرم خلاصه» نسبت به «استنباط نوع» این است که باعث میشود کدمان خوانایی بیشتری داشته باشد. اگر بخواهید آرایهای خالی روی یک کلاس اعلان کنید، دانستن این که دقیقاً چه چیزی قرار بوده ذخیره شود دشوار خواهد بود. با این حال استفاده از اعلان و مقداردهی خلاصه آرایه کاملاً واضح خواهد بود.
بازیابی عناصر از یک آرایه
روشهای مختلفی برای بازیابی یک عنصر از آرایه وجود دارد.
اگر میخواهید تنها یک عنصر را بازیابی کنید و اندیس آن عنصر را میدانید میتوانید از نمادگذاری زیرنویس استفاده کنید:
let arrayOfInts: [Int] = [1، 2، 3، 4] let secondElementOfArray = arrayOfInts[1]
نمادگذاری فوق مقدار 2 را به دست میدهد. اگر میخواهید روی مقادیری در آرایه حلقهای تعریف کنید، نمادگذاری زیرنویس کافی نخواهد بود و باید از ساختار for…in استفاده کنید:
let arrayOfInts: [Int] = [1، 2، 3، 4] for anInt in arrayOfInts { print(“Now printing: \(anInt)”) }
کد فوق هر عنصر آرایه را یک به یک نمایش میدهد تا این که همه آنها نمایش یابند. همچنین میتوانید از مشخصات first و last کلاس آرایه برای دریافت دسترسی امن به ترتیب به عناصر اول و آخر آرایه استفاده کنید. این مشخصات در صورتی که آرایه خالی باشد مقدار تهی (nil) بازمیگردانند. برای نمونه:
let arrayOfInts: [Int] = [1، 2، 3، 4] let firstInt: Int? = arraysOfInts.first let lastInt: Int? = arraysOfInts.last
دو خط کد فوق به ترتیب مقادیر 1 و 4 را بازمیگردانند. دقت کنید که نوع firstInt و lastInt به صورت Int نیستند. آنها از نوع Optional هستند، یعنی میتوانند مقدار Int یا مقدار nil داشته باشند.
افزودن عناصر به یک آرایه
برای افزودن یک عنصر به آرایه بسته به این که بخواهید عنصر به کجای آرایه اضافه شود، راههای مختلفی وجود خواهد داشت. برای افزودن عناصر منفرد به انتهای آرایه میتوان از متد (:_)append استفاده کرد:
var arrayOfInts: [Int] = [1، 2، 3، 4، 5] arrayOfInts.append(6) // arrayOfInts === [1، 2، 3، 4، 5، 6]
برای افزودن عناصر چندگانه به یک آرایه میتوان آرایه یا دنباله دیگری را از هر نوع به متد (:append(contentsOf ارسال کرد. برای نمونه فرض کنید میخواهیم دو آرایه مانند زیر تعریف کنیم:
var firstArray: [Int] = [1، 2، 3] var secondArray: [Int] = [4، 5، 6]
اکنون ببینیم که در حالتهای مختلف چه اتفاقی رخ میدهد:
حالت 1:
firstArray.append(contentsOf: secondArray) // firstArray === [1، 2، 3، 4، 5، 6]
حالت 2:
secondArray.append(contentsOf: firstArray) // secondArray === [4، 5، 6، 1، 2، 3]
شما میتوانید عناصر منفردی را با استفاده از متد (:insert(_:at در هر موقعیت آرایه اضافه کنید:
var arrayOfInts: [Int] = [1، 2، 3، 4، 5] arrayOfInts.insert(6، at: 3) // arrayOfInts === [1، 2، 3، 6، 4، 5]
در نهایت برای افزودن چند عنصر جدید در میانه آرایه میتوانید از متد (:insert(contentsOf:at استفاده کنید:
var firstArray: [Int] = [1، 2، 3] var secondArray: [Int] = [4، 5، 6] firstArray.insert(contentsOf: secondArray، at: 2) // firstArray === [1، 2، 4، 5، 6، 3]
حذف عناصر از یک آرایه
همانند روش افزودن عناصر، بسته به این که عنصر حذفی در انتهای آرایه باشد یا در ابتدا یا میانه آن قرار داشته باشد، میتوان با استفاده از چندین روش اقدام به حذف عناصر از یک آرایه نمود.
برای حذف آخرین عنصر از یک آرایه میتوان از متد ()removeLast استفاده کرد:
var arrayOfInts: [Int] = [1، 2، 3، 4، 5] arrayOfInts.removeLast() // arrayOfInts === [1، 2، 3، 4]
برای حذف عنصری از میانه آرایه میتوان از متد (:remove(at استفاده کرد:
var arrayOfInts: [Int] = [1، 2، 3، 4، 5] arrayOfInts.remove(at: 3) // arrayOfInts === [1، 2، 3، 5] arrayOfInts.remove(at: 0) // arrayOfInts === [2، 3، 5]
برای حذف بازهای از عناصر از یک آرایه میتوان از متد (:_)removeSubrange استفاده کرد:
var arrayOfInts: [Int] = [1، 2، 3، 4، 5، 6] arrayOfInts.removeSubrange(1..<4) // arrayOfInts === [1، 5، 6]
در نهایت برای حذف همه عناصر از یک آرایه میتوان از متد ()removeAll استفاده کند.
آرایهها در زبان Objective C و تفاوت آن با سوئیفت
آرایهها در زبان برنامهنویسی Objective C و سوئیفت شبیه هم نیستند. آرایههای سوئیفت نوعِ مقداری دارند، یعنی در هنگام ارسال، کپی میشوند در حالی که آرایههای Objective C از نوع ارجاعی هستند، یعنی در هنگام ارسال شدن کپی نمیشوند؛ بلکه ارجاعی به آن شیء ارسال میشود.
تفاوت دیگر این است که در سوئیفت هیچ کلاس جداگانهای برای آرایههای تغییرپذیر (mutable) یا تغییرناپذیر (immutable) وجود ندارد. آرایهها در واقع نوعی <Structs<T هستند. برای اعلان یک آرایه به صورت تغییرپذیر یا تغییرناپذیر، باید آنها را به ترتیب با کلیدواژههای var یا let اعلان کنیم. اما به طور عکس در <Structs<T آرایه به صورت یک کلاس پیادهسازی میشود و از این رو کلاسهای جداگانه برای تعیین این که آرایه تغییرپذیر یا تغییرناپذیر است تدارک دیده شده است. از این رو کار با آرایهها در سوئیفت بسیار آسانتر از Objective C است.
کدها در سوئیفت خوانایی بیشتری دارند و مشکلات کمتری رخ میدهد. در ادامه مثالی از شیوه ایجاد آرایه در سوئیفت و Objective C را مشاهده میکنید.
در زبان Objective C کلاس NSArray برای ایجاد یک وهله از آرایه تغییرناپذیر استفاده میشود:
NSArray *stringArray = @[@“One”، @“Two”، @“Three”];
در این کد ما از نمادگذاری خلاصه برای ایجاد آرایه تغییرناپذیر از نوع رشته استفاده کردهایم که شامل سه عنصر است. برای ایجاد یک کپی تغییرپذیر از همین آرایه باید یک وهله از NSMutableArray را به صورت زیر ایجاد کنیم:
NSMutableArray *mutableStringArray = @[@“One”، @“Two”، @“Three”];
برای ایجاد آرایه تغییرپذیر از یک آرایه تغییرناپذیر میتوانیم از متد mutableCopy استفاده کنیم:
NSMutableArray *mutableFromImmutable = [stringArray mutableCopy];
از سوی دیگر چون آرایهها در سوئیفت از نوع مقداری هستند، ایجاد یک آرایه تغییرپذیر از آرایهای تغییرناپذیر به سادگی انتساب یک آرایه تغییرناپذیر به یک متغیر از نوع آرایه مقداری با استفاده از کلیدواژه var به صورت زیر است:
let immutableArray: [String] = [“One”، “Two”، “Three”] var mutableArray: [String] = immutableArray
از آنجا که مقادیر کپی میشوند، گزاره فوق محتوای immutableArray را به mutableArray که تغییرپذیر است، کپی میکند. این قطعه کد بسیار واضحتر و خواناتر است. این یکی از دلایلی است که چرا کار با آرایههای سوئیفت آسانتر کار با آرایههای Objective C است.
در این مقاله ابتدا به معرفی برخی کارکردهای ابتدایی ساختمان داده آرایه پرداختیم. این مواد جزو دانش مقدماتی برای بخشهای بعدی ساختمان دادهها محسوب میشوند.
اگر این مطلب برایتان مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی
- آموزش آرایه در برنامه نویسی Swift (سوئیفت)
- مجموعه آموزشهای پروژه محور برنامهنویسی
- زبان برنامهنویسی سوئیفت را از این منابع به راحتی یاد بگیرید
- آموزش برنامه نویسی Swift (سوئیفت) برای برنامه نویسی iOS
==