fold و reduce

fold و reduce في Dart مع أمثلة 🚀

في Dart، يتم استخدام fold و reduce لتجميع (aggregate) القيم داخل List أو Iterable وتحويلها إلى قيمة واحدة بناءً على عملية محددة.


🔹 reduce()

🔹 تُستخدم reduce() لتطبيق دالة على كل عنصرين متتاليين داخل القائمة، حتى يتم اختزالها إلى قيمة واحدة.
🔹 يجب أن تحتوي القائمة على عنصر واحد على الأقل وإلا ستُسبب خطأ (NoSuchMethodError).

📌 مثال 1: حساب مجموع العناصر

void main() {
  List<int> numbers = [10, 20, 30, 40];

  int sum = numbers.reduce((a, b) => a + b);

  print(sum); // Output: 100
}
Dart

🔹 التفسير:

  • reduce() تأخذ العنصرين الأولين (10 و 20) وتجمعهما 10 + 20 = 30.
  • ثم تجمع الناتج مع العنصر التالي 30 + 30 = 60.
  • ثم تجمع الناتج مع 40 لتصبح النتيجة النهائية 100.

📌 مثال 2: العثور على أكبر عدد

void main() {
  List<int> numbers = [5, 12, 3, 45, 8];

  int maxNumber = numbers.reduce((a, b) => a > b ? a : b);

  print(maxNumber); // Output: 45
}
Dart

🔹 التفسير:

  • يتم مقارنة كل عنصرين متتاليين، والاحتفاظ بالقيمة الأكبر حتى نحصل على أكبر عدد في القائمة.

📌 مثال 3: دمج النصوص

void main() {
  List<String> words = ["Dart", "is", "awesome"];

  String sentence = words.reduce((a, b) => "$a $b");

  print(sentence); // Output: Dart is awesome
}
Dart

🔹 التفسير:

  • يتم دمج النصوص مع وضع مسافة بين كل كلمتين.

⚠️ مشكلة reduce() مع القوائم الفارغة

إذا كانت القائمة فارغة، فستُسبب خطأ:

void main() {
  List<int> emptyList = [];

  int result = emptyList.reduce((a, b) => a + b); // ⚠️ خطأ
}
Dart

الحل: استخدم fold() بدلًا من reduce() لأنه يسمح بتحديد قيمة ابتدائية.


🔹 fold()

🔹 تُستخدم fold() لتطبيق دالة تجميع (aggregation) مع قيمة ابتدائية (initialValue).
🔹 تعمل حتى مع القوائم الفارغة دون مشاكل.

📌 مثال 1: حساب مجموع العناصر باستخدام fold

void main() {
  List<int> numbers = [10, 20, 30, 40];

  int sum = numbers.fold(0, (previous, current) => previous + current);

  print(sum); // Output: 100
}
Dart

🔹 التفسير:

  • 0 هو القيمة الابتدائية.
  • كل عنصر يتم إضافته إلى القيمة السابقة.

📌 مثال 2: ضرب جميع الأرقام مع قيمة ابتدائية 1

void main() {
  List<int> numbers = [2, 3, 4];

  int product = numbers.fold(1, (prev, curr) => prev * curr);

  print(product); // Output: 24
}
Dart

🔹 التفسير:

  • 1 هو القيمة الابتدائية (لأن الضرب ببداية 0 يعطينا 0 دائمًا!).
  • يتم ضرب كل رقم بالقيمة السابقة.

📌 مثال 3: دمج النصوص باستخدام fold

void main() {
  List<String> words = ["Dart", "Flutter", "is", "awesome"];

  String sentence = words.fold("Start:", (prev, curr) => "$prev $curr");

  print(sentence); // Output: Start: Dart Flutter is awesome
}
Dart

🔹 التفسير:

  • Start: هي القيمة الابتدائية للنص.

📌 مثال 4: عد عدد الأحرف في قائمة نصوص

void main() {
  List<String> words = ["Dart", "Flutter", "Coding"];

  int totalCharacters = words.fold(0, (prev, curr) => prev + curr.length);

  print(totalCharacters); // Output: 17
}
Dart

🔹 التفسير:

  • 0 هي القيمة الابتدائية.
  • يتم جمع طول كل كلمة للحصول على العدد الإجمالي للأحرف.

💡 الفرق بين fold و reduce

الدالةهل تحتاج لقيمة ابتدائية؟تعمل مع القوائم الفارغة؟استخداماتها
reduce()❌ لا تحتاج لقيمة ابتدائية❌ تعطي خطأ عند القائمة الفارغةلتقليل (reduce) قائمة إلى قيمة واحدة
fold()✅ تحتاج لقيمة ابتدائية✅ تعمل بشكل جيد مع القوائم الفارغةأكثر مرونة، خاصة عند التعامل مع القوائم الفارغة

📌 مثال يوضح الفرق بين fold و reduce

dartنسختحرير<code>void main() {
  List<int> numbers = [1, 2, 3, 4, 5];

  int sumWithReduce = numbers.reduce((a, b) => a + b);
  int sumWithFold = numbers.fold(0, (a, b) => a + b);

  print(sumWithReduce); // Output: 15
  print(sumWithFold); // Output: 15
}
</code>
Dart

🔹 الفرق الرئيسي يظهر عند استخدام قائمة فارغة.

void main() {
  List<int> emptyList = [];

  // int sumWithReduce = emptyList.reduce((a, b) => a + b); // ⚠️ خطأ
  int sumWithFold = emptyList.fold(0, (a, b) => a + b); // ✅ يعمل بدون مشاكل

  print(sumWithFold); // Output: 0
}
Dart

🔹 التفسير:

  • reduce() لا يمكنها العمل مع قائمة فارغة.
  • fold() يعمل بدون مشاكل لأنه يحتوي على قيمة ابتدائية.

🎯 متى تستخدم fold و reduce؟

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