ترتيب مصفوفة الكائنات في Swift: من البسيط إلى المعقد

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

كيفية ترتيب مصفوفة الكائنات حسب الخاصية في Swift: نظرة تحت الغطاء



مرحباً أيها الزميل! إذا كنت قد كتبت أي وقت مضى تطبيقاً بلغة Swift يعرض قائمة من المستخدمين أو المنتجات أو المهام، فبالتأكيد واجهت الحاجة لترتيب هذه البيانات. سؤال "How to sort an array of custom objects by property value?" هو واحد من أكثر الأسئلة شيوعاً على Stack Overflow. وليس من دون سبب: للوهلة الأولى يبدو كل شيء بسيطاً، ولكن بمجرد التعمق، تنفتح طبقات كاملة من الإمكانيات.



اليوم لن نقدم إجابة جاهزة فقط. سنقوم بتحليل كيفية عمل الترتيب تحت غطاء Swift، وما هي الآليات المستخدمة وكيفية كتابة كود ليس فقط عملياً بل فعالاً وجميلاً. هيا بنا!



ما هو ترتيب مصفوفة الكائنات في Swift؟



تخيل: لديك مصفوفة من الكائنات User. كل مستخدم لديه اسم وعمر وتقييم. تحتاج إلى عرضهم على الشاشة، مرتبين حسب العمر (من الأصغر إلى الأكبر).



في Swift يتم ذلك من خلال الطرق المضمنة sort() (ترتيب المصفوفة في مكانها) و sorted() (إرجاع مصفوفة جديدة مرتبة). كلاهما يقبل إغلاقاً يحدد الترتيب.



struct User {    let name: String    let age: Int    let rating: Double}

let users = [ User(name: "آنا", age: 25, rating: 4.5), User(name: "بوريس", age: 30, rating: 3.8), User(name: "فيكا", age: 22, rating: 4.9)]

// الترتيب حسب العمر (تصاعدياً)let sortedByAge = users.sorted { $0.age < $1.age }print(sortedByAge.map { $0.name }) // ["فيكا", "آنا", "بوريس"]


هذا كل شيء. لكن دعنا نفهم ما يحدث هنا في الواقع.



كيف يعمل sort() تحت الغطاء: الخوارزميات والإغلاقات



تستخدم طريقة sort() في Swift خوارزمية هجينة تسمى TimSort (سميت على اسم تيم بيترز). وهي خوارزمية ترتيب تكيفية ومستقرة تجمع بين ترتيب الدمج وترتيب الإدراج. وهي فعالة بشكل خاص على البيانات المرتبة جزئياً - مرحباً، خلاصات الأخبار وقوائم المهام!



الإغلاق الذي تمرره هو مسند الترتيب: دالة تأخذ عنصرين وتعيد true إذا كان يجب أن يكون الأول قبل الثاني. يستدعي Swift هذا الإغلاق بشكل متكرر، مقارناً أزواج العناصر.



هام: إذا كانت كائناتك تتوافق مع بروتوكول Comparable، يمكنك الاستغناء عن الإغلاق تماماً:



struct User: Comparable {    let name: String    let age: Int        static func < (lhs: User, rhs: User) -> Bool {        return lhs.age < rhs.age    }}

let sortedUsers = users.sorted() // الآن ببساطة


ولكن ماذا لو كنت بحاجة إلى الترتيب حسب خصائص مختلفة في وقت التشغيل؟ هنا تأتي مسارات المفاتيح (KeyPath) للإنقاذ.



الترتيب باستخدام KeyPath: الأناقة والمرونة



بدءاً من Swift 4، لدينا KeyPath. وهي طريقة آمنة للإشارة إلى خاصية كائن. من خلال دمج KeyPath مع الإغلاقات، يمكنك كتابة دالة ترتيب عامة:



extension Array {    mutating func sort<T: Comparable>(by keyPath: KeyPath<Element, T>, ascending: Bool = true) {        sort { ascending ?            $0[keyPath: keyPath] < $1[keyPath: keyPath] :            $0[keyPath: keyPath] > $1[keyPath: keyPath]        }    }        func sorted<T: Comparable>(by keyPath: KeyPath<Element, T>, ascending: Bool = true) -> [Element] {        return sorted { ascending ?            $0[keyPath: keyPath] < $1[keyPath: keyPath] :            $0[keyPath: keyPath] > $1[keyPath: keyPath]        }    }}

// الاستخدام:users.sort(by: \\.age) // حسب العمر (تصاعدياً)let sortedByRating = users.sorted(by: \\.rating, ascending: false) // حسب التقييم (تنازلياً)


جميل، أليس كذلك؟ أمان النوع

المدونات

توصيات الكتب