تفاوت آرایه و مجموعه در زبان سوئیفت — از صفر تا صد

در نگاه نخست آرایه و مجموعه شبیه به هم به نظر میرسند. هر دو آنها انواع کلکسیون هستند و شباهتهای زیادی دارند. اما در اغلب موارد تمایل بیشتری به استفاده از آرایهها در برابر مجموعهها داریم. با این که این وضعیت لزوماً مشکلی ایجاد نمیکند، اما در پارهای موارد استفاده از مجموعه بهتر است. در این مقاله با تفاوت آرایه و مجموعه در زبان سوئیفت آشنا خواهیم شد.
تفاوتهای بنیادی آرایه و مجموعه در زبان سوئیفت
پیش از آن که به بررسی دلایل عملی انتخاب مجموعه یا آرایه بپردازیم، چند اختلاف بنیادی در کار کردن با این دو نوع وجود دارد که آنها را توضیح میدهیم.
مقداردهی
زمانی که مقداردهی یک آرایه را با مجموعه مقایسه میکنیم، میبینیم که کاملاً مشابه هستند:
let arrayOfBlogCategories: [String] = ["Swift", "Debugging", "Xcode", "Workflow", "Optimization"] let setOfBlogCategories: Set<String> = ["Swift", "Debugging", "Xcode", "Workflow", "Optimization"]
هر دو نوع از یک پروتکل ExpressibleByArrayLiteral پشتیبانی میکنند، اما لازم است بدانید که نوع Array Literal به صورت پیشفرض یک آرایه است. با استفاده از کد زیر در نهایت یک آرایه رشته به دست میآید:
let blogCategories = ["Swift", "Debugging", "Xcode", "Workflow", "Optimization"] // Defaults to Array<String>
در نگاه نخست ممکن است فکر کنید هر دو کلکسیون پس از مقداردهی دقیقاً مشابه هم هستند. اما چنین نیست. به توضیح زیر از مستندات توجه کنید:
یک مجموعه مقادیر متمایزی از یک نوع را در کلکسیونی بدون ترتیب خاص ذخیره میکند. در مواردی که ترتیب آیتمها اهمیتی نداشته باشد، یا هنگامی که لازم باشد مطمئن شویم یک پیام تنها یک بار در کلکسیون ظاهر میشود، میتوان از یک مجموعه به جای آرایه استفاده کرد.
به بیان دیگر مجموعه بی ترتیب است، اما آرایه مرتب است. پرینت کردن کلکسیونهای فوق پس از مقداردهی این نکته را مشخص میسازد:
print(arrayOfBlogCategories) // ["Swift", "Debugging", "Xcode", "Workflow", "Optimization", "WWDC"]<br>print(setOfBlogCategories)// ["Xcode", "WWDC", "Swift", "Workflow", "Debugging", "Optimization"]
هنگامی که میخواهید بین این دو ساختمان داده انتخاب کنید، باید به این نکته توجه داشته باشید.
افزودن اشیا
آرایهها و مجموعهها هر دو انواع مقداری هستند. از این رو اگر آنها را به صورت ثابت با استفاده از let تعریف کنید، زمانی که بخواهید شیئی را اضافه کنید با خطایی مانند زیر مواجه میشوید:
چنان که میبینید نخستین تفاوت مشخص شده است. برای آرایه از (:_)append استفاده کردیم، اما در مورد مجموعه (:_)insert استفاده شده است. هر دو متد دستهبندی WWDC را به کلکسیون اضافه میکنند، اما صرفاً در مورد آرایه با اطمینان میتوان گفت که به انتهای لیست اضافه شده است، چون آرایه مرتب است.
تفاوت دیگر در نوع بازگشتی متد (:_)insert است این متد هر دو نوع بولی inserted و مشخصه memberAfterInsert را بازگشت میدهد که یا شامل شیء از پیش موجود و یا شیء درج شده است. این وضعیت در مواردی که بخواهید بازخوردی به کاربر بدهید که آیا شیئی از قبل وجود دارد یا نه مفید خواهد بود:
let (inserted, memberAfterInsert) = setOfBlogCategories.insert("Swift") if !inserted { print("\(memberAfterInsert) already exists") } // Prints: "Swift already exists"
یکتایی عناصر
یکی از مهمترین تفاوتهای بین مجموعهها و آرایهها، یکتایی عناصر است. یک آرایه میتواند شامل مقادیر تکراری باشد، اما مجموعه هرگز مقدار تکراری ندارد. به همین دلیل است که متد (:_)insert فوق یک مقدار بولی بازگشت میدهد تا متوجه شویم که درج عملاً رخ داده است یا نه. این تفاوت مهمی است و به همان دلیل است که باید از مجموعه استفاده کنید تا نیازی نباشد از یک فیلتر روی آرایه برای جلوگیری از درج عناصر تکراری بهره بگیرید.
ترتیب عناصر
یکی از مهمترین تفاوتهای بین آرایه و مجموعه، ترتیب عناصر است. مستندات چنین بیان میکنند:
- آرایه: یک کلکسیون مرتب با دسترسی تصادفی است.
- مجموعه: یک کلکسیون نامرتب از عناصر یکتا است.
از این رو اگر ترتیب عناصر مهم باشد، باید از آرایه استفاده کنیم.
نوع NSOrderedSet
یک نوع دیگر نیز به نام NSOrderedSet وجود دارد. اما این نوع سوئیفت نیست و هزینه سرباری دارد. از آنجا که یک نوع غیر ژنریک است باید با اشیای Any کار کنیم و هر جا که از آن استفاده میکنیم از تبدیل نوع بهره بگیریم.
اما NSOrderedSet یک جایگزین مرتب عالی برای آرایهها محسوب میشود و باید در مواردی که عملکرد تست عضویت یک عنصر حائز اهمیت است، مورد استفاده قرار گیرد. تست این که یک شیء در یک مجموعه قرار دارد یا نه سریعتر از تست عضویت یک آرایه است. NSOrderedSet یک نوع کلکسیون استاتیک است و پس از مقداردهی امکان افزودن یا حذف ندارد. به همین جهت استفاده از آن به جای آرایه مناسب است.
تفاوت عملکرد
دلیل دیگر استفاده از یک مجموعه این است که وقتی با دادههای زیادی سر و کار داریم، عملکرد اهمیت مییابد. عناصر در یک مجموعه باید با پروتکل Hashable سازگار باشند و از این رو مجموعه برای عملکرد بهینه شده است. گشتن به دنبال یک عنصر در یک کلکسیون کوچک و بزرگ به مقدار زمان یکسانی نیاز دارد.
به طور کلی بهتر است جهت ارتقای عملکرد در موارد امکان، کلکسیونهای تغییرناپذیر (immutable) ایجاد کنیم. این نکته در مورد هر دو نوع آرایه و مجموعه صدق میکند و به کامپایلر سوئیفت امکان میدهد که عملکرد کلکسیونهایی که ایجاد میشوند را بهینهسازی کند.
دادههای اصلی، NSSet و تبدیل انواع در سوئیفت
زمانی که با کلکسیونهای در «دادههای اصلی» (Core Data) کار میکنیم، گاهی وسوسه میشویم که با «مجموعه نوعدار» (typed Set) کار کنیم. البته این کار هزینهای دارد که شاید همواره بیدرنگ ظاهر نشود.
اگر کلکسیون دادههای اصلی یک مقدار ثابت است و تغییرات زیادی نخواهد داشت، بهتر است با متد copy(with:) به یک مجموعه پل بزنید که به محض پل زدن همان مجموعه در زمان ثابت بازگشت مییابد. عملکرد کپی یک نوع NSSet تغییرپذیر نامشخص است.
سخن پایانی
در این مقاله با تفاوتهای مجموعه و آرایه آشنا شدیم. این تفاوتها را میتوان به صورت زیر جمعبندی کرد که در موارد زیر بهتر است از آرایه استفاده کنید:
- ترتیب مهم باشد.
- عناصر تکراری امکانپذیر باشند.
- عملکرد مهم نباشد.
در موارد زیر نیز استفاده مجموعه مناسبتر است:
- ترتیب مهم نباشد.
- عناصر یکتا یک الزام باشد.
- عملکرد مهم باشد.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویس
- آموزش برنامه نویسی Swift (سوئیفت) برای برنامه نویسی iOS
- مجموعه آموزشهای دروس علوم و مهندسی کامپیوتر
- آموزش سوئیفت (Swift) — مجموعه مقالات مجله فرادرس
- آموزش برنامه نویسی سوئیفت (Swift): مفهوم ژنریک ها (Generics) – بخش سیزدهم
==