دوال Higher-Order مخصصة
جزء من قسم المنطق والتدفق في رحلة Swift على Coddy — الدرس 42 من 56.
الآن يمكنك كتابة الدوال الخاصة بك من الرتبة الأعلى (higher-order functions) وستتناسب تماماً مع map و filter. الشكل دائماً هو نفسه: تأخذ معامل closure، وتستدعيه داخل الحلقة، ثم تعيد النتيجة.
extension Array {
func myMap<T>(_ transform: (Element) -> T) -> [T] {
var result: [T] = []
for item in self {
result.append(transform(item))
}
return result
}
}
[1, 2, 3].myMap { $0 * 10 } // [10, 20, 30]إذا كانت الامتدادات تبدو أكثر من اللازم، فاكتب دالة مستقلة بدلاً من ذلك، فالفكرة هي نفسها:
func count<T>(_ items: [T], where predicate: (T) -> Bool) -> Int {
var n = 0
for item in items where predicate(item) {
n += 1
}
return n
}بمجرد أن تتمكن من تمرير الـ closures، تتوقف المكتبة القياسية عن الظهور كالسحر وتبدأ في الظهور كمجموعة من الأنماط التي يمكنك كتابتها بنفسك.
التحدي
متوسطاكتب دالة حرة partition(_ items: [Int], by predicate: (Int) -> Bool) -> ([Int], [Int]) تقوم بالمرور على المصفوفة مرة واحدة وتعيد صفاً (tuple) (matched, rest): العناصر التي استوفت الشرط (predicate)، والبقية، كلاهما بنفس الترتيب الأصلي.
اقرأ سطرين: عدد صحيح min، ثم قائمة من الأعداد الصحيحة مفصولة بفاصلة. استخدم دالة partition الخاصة بك مع شرط (predicate) يتحقق مما إذا كان n > min. اطبع:
matched: <...>rest: <...>
كل قائمة يتم دمج عناصرها باستخدام , (أو تترك فارغة عندما لا يوجد شيء لطباعته).
للمدخلات 5 / 2,7,3,8,5، المخرجات هي:
matched: 7,8
rest: 2,3,5ورقة مرجعية
تتبع الدوال ذات الرتبة الأعلى نمطاً ثابتاً: استقبال closure، واستدعاؤه داخل حلقة تكرارية، ثم إرجاع النتيجة.
كملحق (extension):
extension Array {
func myMap<T>(_ transform: (Element) -> T) -> [T] {
var result: [T] = []
for item in self {
result.append(transform(item))
}
return result
}
}
[1, 2, 3].myMap { $0 * 10 } // [10, 20, 30]كدالة حرة (free function):
func count<T>(_ items: [T], where predicate: (T) -> Bool) -> Int {
var n = 0
for item in items where predicate(item) {
n += 1
}
return n
}دالة partition تُرجع صفاً (tuple) من العناصر المتطابقة وغير المتطابقة:
func partition(_ items: [Int], by predicate: (Int) -> Bool) -> ([Int], [Int]) {
var matched: [Int] = []
var rest: [Int] = []
for item in items {
if predicate(item) { matched.append(item) }
else { rest.append(item) }
}
return (matched, rest)
}جرّب بنفسك
let min = Int(readLine()!)!
let nums = readLine()!.components(separatedBy: ",").map { Int($0)! }
// مهام مطلوبة: partition(_:by:) -> ([Int], [Int])؛ طباعة العناصر المتطابقة والباقي
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس المنطق والتدفق
1النصوص بعمق
العد والفهارسحالة الأحرف وإزالة الفراغاتالبحث في النصوصتقسيم ودمج النصوصاستبدال النصوص الفرعيةمراجعة - التحقق من اسم المستخدم4المجموعات
إنشاء المجموعاتالاتحاد والتقاطعالطرح والفرق المتماثلالمجموعات الجزئية والشاملةمراجعة - تصفية الـ Tag7مشروع - متتبع العادات
نظرة عامة على المشروعتحديد كمكتمل2النطاقات والخطوات
المغلقة مقابل نصف المفتوحةالخطوة (Stride)دوال النطاقاتالنطاقات في Switchملخص - شبكة التقويم5الدوال من الرتبة العليا - الجزء الأول
MapFilterReduceربط Map و Filter و Reduceمراجعة - إحصائيات الكلمات8Closures
أساسيات ClosuresTrailing Closuresالتقاط القيمإرجاع Closuresدوال Higher-Order مخصصةمراجعة - بناء Pipeline