مقدمة: لماذا يعتبر "العثور على الفهرس" أساسياً يجب إتقانه
\n\nتخيل أنك تبني تطبيق iOS. لديك مصفوفة من المهام، ويريد المستخدم حذف مهمة محددة باسمها. أو ربما تبحث عن موقع عنصر لتحديثه في القائمة. في كلتا الحالتين، تحتاج إلى نفس الشيء — العثور على فهرس عنصر في مصفوفة Swift. هذه المهمة شائعة جداً لدرجة أن سؤالاً عنها على Stack Overflow حصد آلاف المشاهدات. وهذا ليس من قبيل الصدفة: البحث عن الفهرس هو أحد أكثر السيناريوهات تكراراً في التطوير اليومي.
\n\nفي هذا الدليل، سنستعرض جميع الطرق للعثور على فهرس عنصر في Swift: من firstIndex(of:) البسيط إلى البحث المتقدم باستخدام closures. ستتعلم كيفية العمل مع مصفوفات النصوص والأرقام والكائنات المخصصة. هيا بنا!
1. التحضير: ما هو الفهرس في مصفوفة Swift؟
\n\nقبل أن نبدأ بالكود، دعنا نراجع الأساسيات. المصفوفة في Swift هي مجموعة مرتبة من العناصر. كل عنصر له فهرس — رقم صحيح يبدأ من 0. العنصر الأول فهرسه 0، والثاني 1، وهكذا.
\n\nlet fruits = ["🍎 تفاح", "🍌 موز", "🍒 كرز"]\n// الفهارس: 0 1 2\n\n\nعندما نقول "العثور على فهرس عنصر"، نعني: "أرجع رقم الموقع الذي يوجد فيه هذا العنصر". في Swift، هناك عدة طرق أنيقة للقيام بذلك. دعنا نستعرضها بالترتيب.
\n\n2. الطريقة التقليدية: firstIndex(of:) — أسهل مسار
\n\nابتداءً من Swift 4.2، أصبحت طريقة firstIndex(of:) هي الطريقة القياسية للبحث عن فهرس عنصر. تُرجع قيمة اختيارية Int? — إذا تم العثور على العنصر، تحصل على الفهرس؛ وإلا تحصل على nil.
مثال مع مصفوفة نصوص
\n\nlet fruits = ["تفاح", "موز", "كرز", "تمر"]\n\nif let index = fruits.firstIndex(of: "كرز") {\n print("فهرس 'كرز': \\(index)") // سيطبع: 2\n} else {\n print("العنصر غير موجود")\n}\n\n\nلاحظ: firstIndex(of:) يبحث عن أول ظهور. إذا كانت المصفوفة تحتوي على عناصر مكررة، فسيعيد الفهرس الأول فقط.
مثال مع مصفوفة أرقام
\n\nlet numbers = [10, 20, 30, 40, 50]\n\nif let position = numbers.firstIndex(of: 30) {\n print("الرقم 30 موجود في الموقع \\(position)") // 2\n}\n\n\nهام: هذه الطريقة تعمل فقط مع الأنواع التي تتوافق مع بروتوكول Equatable. جميع الأنواع القياسية (Int, String, Double, Bool) متوافقة معه بالفعل.
3. البحث بشرط: firstIndex(where:) — مرونة بلا حدود
\n\nماذا لو كنت بحاجة للعثور على فهرس ليس بناءً على قيمة محددة، بل بناءً على شرط؟ مثلاً، العثور على أول عنصر أكبر من 25، أو نص يبدأ بحرف معين. لهذا الغرض، توجد طريقة firstIndex(where:) (المعروفة سابقاً بـ index(where:)).
الصيغة مع closure
\n\nlet scores = [15, 22, 37, 41, 19]\n\nif let index = scores.firstIndex(where: { $0 > 25 }) {\n print("أول عنصر أكبر من 25 موجود في الفهرس \\(index)") // 2 (القيمة 37)\n}\n\n\nالبحث حسب خاصية كائن
\n\nلنفترض أن لديك مصفوفة من الهياكل المخصصة:
\n\nstruct User {\n let name: String\n let age: Int\n}\n\nlet users = [\n User(name: "سارة", age: 25),\n User(name: "خالد", age: 30),\n User(name: "نور", age: 22)\n]\n\n// ابحث عن فهرس المستخدم باسم "خالد"\nif let index = users.firstIndex(where: { $0.name == "خالد" }) {\n print("خالد موجود في الفهرس \\(index)") // 1\n}\n\n\nهذا الأسلوب قوي بشكل لا يصدق. يمكنك استخدام أي شرط منطقي: التحقق من عدة خصائص، استخدام التعبيرات المنتظمة، أو حتى استدعاء دوال داخل الـ closure.
\n\n4. التعامل مع العناصر المكررة: كيفية العثور على جميع الفهارس
\n\nم