Fold مقابل Reduce في Kotlin: متى تستخدم كل منهما؟ تحليل شامل

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

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

ابدأ الدورة

Fold أم Reduce في Kotlin: السؤال الأبدي للمبتدئين

\n\n

إذا كنت تكتب بلغة Kotlin لمدة أسبوع على الأقل، فمن المحتمل أنك قد صادفت الدالتين fold و reduce. للوهلة الأولى، تقومان بنفس الشيء: تمران على المجموعة ويجمعان النتيجة. لكن الشيطان، كما هو الحال دائمًا، يكمن في التفاصيل. الاختيار الخاطئ قد يؤدي إلى أخطاء برمجية، استثناءات، أو ببساطة إلى كود غير أنيق.

\n\n

في هذه المقالة، سنحلل الفرق بين fold و reduce في Kotlin، وننظر إلى أمثلة حية من مشاريع حقيقية، ونتذكر إلى الأبد متى نستخدم أي دالة. هيا بنا!

\n\n

ما هما fold و reduce؟ فهم أساسي

\n\n

كلتا الدالتين تنتميان إلى العمليات النهائية للمجموعات. تأخذان جميع العناصر وتجمعهما في قيمة واحدة. تخيل أن لديك كومة من الفطائر وتريد الحصول على برغر واحد كبير. fold و reduce هما طريقتان مختلفتان للطي.

\n\n

Reduce: نهج بسيط

\n\n

تستخدم الدالة reduce العنصر الأول من المجموعة كقيمة أولية للمراكم. هذا يعني أنها لا تستطيع العمل مع مجموعة فارغة - سيتم إلقاء UnsupportedOperationException.

\n\n
val numbers = listOf(1, 2, 3, 4, 5)\nval sum = numbers.reduce { acc, i -> acc + i }\nprintln(sum) // 15
\n\n

هنا، acc يساوي في البداية 1 (العنصر الأول)، ثم يضاف إليه 2، ثم 3، وهكذا. الأمر بسيط وأنيق، لكن هناك فارق بسيط.

\n\n

Fold: التحكم في البداية

\n\n

على عكس reduce، تتطلب fold تحديد قيمة أولية بشكل صريح. هذا يمنحك تحكمًا كاملاً، والأهم من ذلك، يسمح لك بالعمل مع المجموعات الفارغة.

\n\n
val numbers = listOf(1, 2, 3, 4, 5)\nval sum = numbers.fold(0) { acc, i -> acc + i }\nprintln(sum) // 15\n\nval emptyList = listOf<Int>()\nval emptySum = emptyList.fold(0) { acc, i -> acc + i }\nprintln(emptySum) // 0, لا يوجد خطأ!
\n\n

هل ترى الفرق؟ fold تُرجع القيمة الأولية إذا كانت المجموعة فارغة. reduce في هذه الحالة ستتعطل.

\n\n

الاختلافات الرئيسية بين fold و reduce في Kotlin

\n\n

دعونا ننظم المعرفة. إليك جدول سيساعدك على التوجيه بسرعة:

\n\n
    \n
  • القيمة الأولية: في fold تحددها بنفسك. في reduce هي العنصر الأول من المجموعة.
  • \n
  • نوع النتيجة: في fold يمكن أن يختلف نوع النتيجة عن نوع العناصر (مثلاً، تجمع Int وتحصل على String). في reduce يتطابق نوع النتيجة دائمًا مع نوع العناصر.
  • \n
  • المجموعة الفارغة: fold تتعامل معها بشكل طبيعي (تُرجع القيمة الأولية). reduce تُلقي استثناءً.
  • \n
  • الأداء: كلتا الدالتين تعملان بزمن O(n). الفرق في الأداء غير ملحوظ.
  • \n
\n\n

الآن دعونا نرى ذلك في الكود.

\n\n

مثال 1: أنواع مختلفة للمراكم والعناصر

\n\n

لنفترض أن لدينا قائمة أرقام، ونريد الحصول على سلسلة نصية - مجموعها بشكل قابل للقراءة. fold تتعامل مع هذا بشكل ممتاز، لأن نوع المراكم (String) يختلف عن نوع العناصر (Int).

\n\n
val numbers = listOf(1, 2, 3)\nval result = numbers.fold("المجموع: ") { acc, i -> "$acc$i " }\nprintln(result) // "المجموع: 1 2 3 "
\n\n

حاول فعل نفس الشيء مع reduce - سيعطيك المترجم خطأً، لأن reduce تتطلب أن يتطابق نوع المراكم مع نوع العناصر.

\n\n

مثال 2: حساب المجموع مع مراعاة القيمة الأولية

\n\n

مهمة شائعة: حساب المجموع الإجمالي للطلبات، لكن لدينا بالفعل رصيد أولي في الحساب.

\n\n
val orders = listOf(100, 250, 75)\nval initialBalance = 500\nval totalBalance = orders.fold(initialBa                

المدونات

توصيات الكتب