---
title: Using Arrayprototypereduce to Reduce Conceptual Boilerplate for Problems on Arrays
localeTitle: استخدام Arrayprototypereduce لخفض Boilerplate المفاهيمي لمشاكل على صفائف
---
هذا تماما الفم! يمكن أن يكون قد تم للتو بعنوان **استخدام `Array.prototype.reduce()` لحل مشاكل صفيف بسهولة** أو **`Array.prototype.reduce()` FTW!** . كان من الأسهل قراءة هذا الأمر وتحليله.

لكنه لم يكن. الحلقات في JavaScript هي مثل ذلك. فهي ليست مقتضبة ، فهي تجعلك تتفوق على الأدغال لفترة من الوقت. كما تذهب النكتة ، هناك شيئان أكثر صعوبة في علوم الكمبيوتر - [إبطال ذاكرة التخزين المؤقت](https://en.wikipedia.org/wiki/Cache_invalidation) [وتسمية الأشياء](https://www.quora.com/Why-is-naming-things-hard-in-computer-science-and-how-can-it-can-be-made-easier) [وخطأ واحد تلو الآخر](https://en.wikipedia.org/wiki/Off-by-one_error) .

ثم هناك خطر كتابة [رمز غير قانوني داخل حلقة بدون استخدام إغلاق من IIFE](http://stackoverflow.com/questions/11488014/asynchronous-process-inside-a-javascript-for-loop) .

تبدأ هذه المقالة مع مطالبة - يمكنك تجنب استخدام حلقة for-loop أو أثناء الحل لحل أي مشاكل متعلقة `Array` . بدلا من ذلك ، يمكنك حل كل منهم باستخدام `Array.prototype.reduce()` . إذا كنت ترغب في القراءة ؛ تأكد من معرفتك للوظائف العودية ، وبعض الأدوات الوظيفية الرائعة مثل `Array.prototype.map()` أو `Array.prototype.filter()` .

المطالبات الكبرى تتطلب أدلة كبيرة. لذا دعنا نوضح كيف يمكننا الاعتياد على استخدام `reduce()` .

لقد حان الوقت لأنك تعلم ، أنه إذا لم تحل أقسام البرمجة النصية خوارزمية FreeCodeCamp ، قد ترغب في إيقاف قراءة هذا الجزء التالي. بعض الأمثلة يمكن أن تطابق هذه المشاكل.

هذا هو التنبيه المفسد الكلي. للتأكد من أنك تعطي هذه المشاكل محاولة صادقة ولا تأخذ نظرة خاطفة على الحلول قبل أن تحاول حتى.

أيضًا ، إذا كنت قد فهمته جيدًا بما فيه الكفاية ، فربما ترغب في مراجعة هذا الجزء من الكتابة وتقديم التعليقات.

## هل يمكنني تقليل مشكلة ذات صلة بـ Array؟

نعم تستطيع! في الواقع ، لا تحتاج المشكلة إلى مصفوفة - _بل يجب أن تكون مشكلة ، حيث يمكنك إنشاء صفيف وسيط_ .

دعونا نأخذ مثالا. من الشائع جدًا إنشاء [رابط](https://en.wikipedia.org/wiki/Semantic_URL#Slug) عناوين [URL](https://en.wikipedia.org/wiki/Semantic_URL#Slug) من السلسلة القياسية ذات المسافات البيضاء مثل عناوين الأخبار أو عناوين مقالات المدونات أو حتى أسئلة حول منتديات الأسئلة والأجوبة.

قل ، علينا كتابة وظيفة الأداة ، التي تخلق هذه السلاجقة. ربما يمكنك كتابة شيء كهذا:

 `function createSlug(str){ 
  return str.split(" ").reduce(function(prev, next){ 
    return prev.concat(<a href='https://signalvnoise.com/posts/3124-give-it-five-minutes' target='_blank' rel='nofollow'>next.toLowerCase()]); 
  }, []) 
  .join("-"); 
 } 
` 

لاتأخذ كلماتي على محمل الجد! المضي قدما ، واختبارها في وحدة التحكم الخاصة بك مع بعض المدخلات مثل "ليو في النهاية يفوز بجائزة أوسكار!" انظر ما يعود. سأنتظر ... انتهى؟ حسنا ، المضي قدما.

نعم ، إنه ليس تطبيقًا قويًا. لا يعتني ببعض حالات الحواف ، كما يفترض أن يحدث الانضمام مع `"-"` .

لكن هذه بداية. لاحظ كيف أن استخدام `reduce` يأخذ `reduce` القياسي من طريقك - يحدث الإجراء فقط في السطر:

 `return prev.concat([next.toLowerCase()]); 
` 

هذا هو جوهر الوظيفة التي نريدها. في الواقع ، نحن مطمئنون جدا من روعتها ، أن نبدأ هيئة `function` مع بيان `return` !

قد تتخيل أن هذا يبدو مثل السحر المظلم. تأكد من أن هذا ليس رد فعل غير مهذب ، لأنك معتاد على كتابة الحلقات. فقط \[امنحه خمس دقائق!

إذا لم تكن الشفرة الواردة أعلاه واضحة ، فأنت بحاجة إلى فهم كيفية `reduce` الأعمال. _وفهمت_ ، أعني ، أعلم أنه مثل ظهر يدك.

## لكنني لا أفهم الخفض على الإطلاق!

حسنا ، لا تخف! أنت على وشك `reduce` النينجا في الدقائق القليلة القادمة.

تحتوي كل وظيفة من مهام JavaScript على ثلاثة أشياء تحتاج إلى معرفتها ، لفهم كيفية عمل الوظيفة:

*   المدخل
*   الإخراج
*   سياق التنفيذ

نعم ، يمكنني رؤيتك فتح [وثائق MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce) الرسمية في علامة تبويب جديدة! كل شيء على مايرام ، اذهب للقراءة أولاً. أنا جاد ، هذه ليست مزحة.

يجب أن تبدأ دائمًا في الوثائق الرسمية لفهم شيء ما.

جيد ، والآن بعد أن كنت مرتبكة مع `prev` `next` داخل رد الاتصال ؛ أنت على استعداد لمتابعة النص هنا.

يأخذ `Array.prototype.reduce()` استدعاء والقيمة الأولية `Array.prototype.reduce()` الإدخال (القيمة الأولية مهمة. الكثير من المطورين ننسى توفير القيمة الأولية بشكل صحيح ؛ `Array.prototype.reduce()` ).

كما يجب أن تكون قد شاهدت في الوثائق ، فإنه يتطلب بعض الحجج الإضافية ولكن اختياري أيضا. ولكن أكثر عن ذلك لاحقا. على افتراض `arr` هو مجموعة عشوائية.

 `arr.reduce(function(){}, initialValue); 
` 

الآن ، دعونا نلقي نظرة فاحصة على وظيفة رد الاتصال ، والتي هي أول حجة `reduce` من. هذا الاستدعاء ، بدوره ، يأخذ اثنين من الحجج. يتم استدعاء هاتين الحججتين في الوثائق الرسمية في `prev` `next` . أنا شخصياً لا أعتقد أن هذه الأسماء تنصف طبيعتها الحقيقية.

لذا ، في جميع أنحاء هذا النص ، سنكون نشير إليها على أنها " `acc` ، لتمثيل القيمة المتراكمة ؛ `item` ، للدلالة على العنصر الحالي الذي يتم الوصول إليه.

مع هذه حتى الآن ، إليك ما يجب أن يبدو عليه `reduce` :

 `arr.reduce(function(acc, item){ 
 /* here you have to complete the function */ 
 }, initialValue); 
` 

الآن، دعونا معرفة ما قيمة هذه `acc` و `item` هي. لقد ذكرنا في وقت سابق أن `reduce` هو بديل للإنشاءات المتكررة.

من المنطقي أن `reduce` سيأخذ وظيفة رد الاتصال المخصصة الخاصة بك؛ وأعاد على صفيف التي `reduce` قد احتج بها.

بدلا من وصف هذه ، دعنا نسأل محرك JS التنفيذ ما هي هذه!

 `var arr = <a href='http://javascriptissexy.com/understand-javascripts-this-with-clarity-and-master-it/' target='_blank' rel='nofollow'>10, 20, 30, 60]; 
 arr.reduce(function(acc, item){ 
   console.log(acc, item); 
 }, 0); 
` 

تنفيذ ما ورد أعلاه في المستعرض أو وحدة تحكم عقدة سيعطيك هذا كخرج:

 `0 10 
 undefined 20 
 undefined 30 
 undefined 60 
` 

لاحظ أن عدد المخرجات هو نفس عدد العناصر في المصفوفة `[10, 20, 30, 60]` . في الواقع ، فإنه يطبع عناصر مصفوفة!

لذلك ، يمكننا أن نستنتج أن `reduce()` يأخذ رد الاتصال المخصص وينفذها على كل عنصر من عناصر المصفوفة. أثناء القيام بذلك ، فإنه يجعل العنصر الحالي متاحًا للمعاودة المخصصة كوسيطة `item` .

ولكن ماذا عن `acc` ؟ نرى ذلك بخلاف السطر الأول ، عندما يكون `item = 10` ، غير `undefined` . في السطر الأول ، الذي يتوافق مع التكرار الأول ، تكون قيمته هي نفس القيمة `initialvalue` .

باختصار ، لدينا تراكم `acc` ، لا تراكم!

ولكن بعد ذلك ، كيف نجعلها تتراكم؟ دعونا نحاول تنفيذ هذا:

 `var arr = [10, 20, 30, 60]; 
 arr.reduce(function(acc, item){ 
   console.log(acc, item); 
   return acc; 
 }, 0); 
` 

هذه المرة يتغير الإخراج إلى:

 `0 10 
 0 20 
 0 30 
 0 60 
` 

كما ترون ، ستبقى قيمة `acc` ثابتة طوال الوقت. وهذا متوقع - نحن لا نغير قيمة `acc` في أي مكان في رد الاتصال المخصص. نعود أي `reduce` يجعل متاح في التكرار.

لكننا أدركنا شيئًا - قيمة `acc` في التكرار الحالي ، ستكون قيمة `return` من رد الاتصال المخصص من التكرار السابق. وفي النهاية ، عندما ينتهي التكرار ، سيتم إرجاع القيمة النهائية لـ `acc` من خلال `reduce` الاتصال.

هذا يترك جزءًا مهمًا واحدًا فقط في فهمنا - قيمة سياق التنفيذ ، أو \[ `this` !

لذا ، نقترب مرة أخرى من جارنا الودي ، وحدة التحكم JS وننفذ هذا:

 `var arr = <a href='https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode' target='_blank' rel='nofollow'>10, 20, 30, 60]; 
 arr.reduce(function(acc, item){ 
   console.log(acc, item, this); 
   return acc; 
 }, 0); 
` 

إذا كنت في \[وضع صارم ، فإنه سيعود `undefined` كقيمة `this` . خلاف ذلك ، في المتصفح ، فإنه يشير إلى كائن [`window`](https://developer.mozilla.org/en-US/docs/Web/API/Window) على `this` النحو. يمكننا التغلب عليها ووضعها بمفردنا ، باستخدام [`bind`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind) ؟ بالتأكيد! فقط استخدم `bind` مع معاودة الاتصال:

 `var arr = <a href='https://en.wikipedia.org/wiki/Loop_invariant' target='_blank' rel='nofollow'>10, 20, 30, 60]; 
 arr.reduce(function(acc, item){ 
   console.log(acc, item, this); 
   return acc; 
 }.bind(arr), 0); 
` 

لقد ربطت صفيف `arr` نفسها ؛ ولكن يمكنك ضبطه على أي كائن في بيئتك.

## فهم تقليل

دعونا نلخص فهمنا لوظيفة `reduce` هذه لتسهيل الرجوع إليها:

*   يأخذ "الحد" رد اتصال مخصصًا كوسيطة أولى له ، وبعض القيمة الأولية كوسيطة ثانية له.
*   من المهم ألا ننسى الحجة الثانية ، القيمة الأولية ؛ ونقوم بتعيينها بوضوح أثناء استخدامها.
*   يتم دمج الوسائط الإدخال إلى رد الاتصال المخصص `acc` ؛ والعنصر الحالي في المصفوفة ، `item` .
*   ستكون قيمة `acc` للتكرار التالي القيمة التي تم إرجاعها من داخل معاودة الاتصال ، بالتكرار الحالي.
*   نقطة كاملة من استخدام `reduce()` هو تشكيل `acc` بشكل صحيح. لإعادته أخيرًا من استدعاء `reduce()` .

لا تحاول تذكرها عن طريق الحذف! بدلا من ذلك ، دعونا نتذكرها بتطبيقها في الكود الحقيقي.

## باستخدام Reduce

دعونا نبدأ عملية مصفوفة بسيطة من أعلى رأسنا - _إيجاد الحد الأقصى في مجموعة_

من أجل الإيجاز ، أفترض أنه عبارة عن صفيف صحيح.

لتكوين حل ، نحتاج إلى التفكير في كيفية تكوين `acc` كما `reduce` ، والتي تستدعي معاودة الاتصال لدينا وتتكرر عبر المصفوفة.

الفكرة التي أجدها مفيدة ، هي التفكير من حيث \[\[\[\]\]\] loop-invariants. نحن نريد التوصل إلى صيغة بغض النظر عن حجم أو محتوى الصفيف ؛ `acc` ينبغي أن يكون دائما القيمة القصوى حتى الآن.

Say، My Array is `[20, 50, 5, 60]` . بعد اثنين من التكرار ؛ `item` سيكون `5` و `acc` ينبغي أن يكون `max(20, 50) = 50` .

الطريقة الوحيدة `acc` يحصل دائما الحد الأقصى من _subarray اجتاز حتى الآن،_ هو ما اذا كنا دائما اختيار أقصى الحالي `item` و `acc` - والعودة هو الفائز!

إذن ، ما هي الوظيفة التي ستبدو عليها:

 `var arr = [20, 50, 5, 60]; 
 arr.reduce(function(acc, item){ 
  return Math.max(acc, item); 
 }, 0); 
` 

قد يكون من المغري إعادة كتابتها كما يلي ، بالترادف مع مبادئ البرمجة الوظيفية ؛

 `var arr = [20, 50, 5, 60]; 
 arr.reduce(Math.max, 0); 
` 

لكن هذا لن ينجح وسيعود `NaN` . هذا هو السبب - لا تعتبر `item` `acc` و `item` الوسيطات **الوحيدة** لمعاودة الاتصال المخصصة. عند استدعاء [`Math.max()`](//forum.freecodecamp.com/t/javascript-math-max/14682) يحاول استدعاء على وسائط غير رقمية ، ينتج `NaN` .

لاحظ أنني لم أفكر كثيرًا في اختيار القيمة الأولية. أنا فقط اختار أنها `0` ؛ مما أدى إلى خلل!

إذن ، ماذا لو كان صفيفي يتألف من قيم أقل من الصفر؟ Say، `arr = <a href='https://en.wikipedia.org/wiki/Least_common_multiple' target='_blank' rel='nofollow'>-7, -56, -5, -2]` . ستكون القيمة التي تم إرجاعها `0` ، وهو غير موجود في Array `arr` .

بدلاً من ذلك ، يجب أن نختار أدنى قيمة ممكنة للقيمة الأولية.

 `var arr = [-20, -50, -5, -60]; 
 arr.reduce(function(acc, item){ 
  return Math.max(acc, item); 
 }, -Infinity); 
` 

نحن للوصول الى هناك. يجب علينا صقل مهاراتنا في مشكلة أخرى مرتبطة بالصفيف. فقط للحصول على بعض المتعة ، دعونا نذهب مع واحد أكثر صرامة.

لنفترض أننا وجدنا \[LCM من مجموعة من الأعداد الصحيحة. الآن ، من الناحية النظرية ، نحن نعلم أن المضاعف المشترك الأصغر لعددين سيكون نتاجًا لهم ، مقسومًا على [HCF الخاص](https://en.wikipedia.org/wiki/Greatest_common_divisor) بهم.

توجد خوارزمية Eucledian لإيجاد HCF ؛ وفيرة هي تنفيذها. لا توجد نقطة تضيع وقتك مما يجعلك تكتب وظيفة HCF عندما يمكنك كتابة واحدة بنفسك ، أو يمكنك العثور على واحد.

بدلاً من ذلك ، دعنا نلقي نظرة على كيفية تمديد LCM من رقمين في LCM لأعداد متعددة. Newsflash - ليس نتاج مصفوفة كاملة مقسومة على HCF الخاص بهم. كلا. سيكون ذلك خطأ رياضيا.

سيكون LCM من ثلاثة أرقام LCM من أول رقمين ؛ ثم LCM من LCM الأول مع الرقم المتبقي. وبالمثل ، يمكنك صياغة استراتيجية لاكتشاف LCM من المصفوفة الفرعية أولاً ، ثم أخذ رقم آخر والعثور على LCM الخاص به مع LCM الأولى.

إذن ، كيف نصوغ الحل؟ نحن بحاجة إلى التفكير في `acc` في منتصف التكرار. يجب أن تكون `acc` النهائية LCM للمجموعة بأكملها ، بلا شك. لكن خلال التكرار `nth` أيضا ؛ يجب أن تحمل `acc` المضاعف المشترك الأصغر لعناصر `(n-1)` التي تم اجتيازها حتى الآن.

ونعم ، القيمة الأولية. يجب أن يكون رقمًا ، سيكون LCM مع رقم آخر هو الرقم الآخر. من الواضح ، هو `1` .

دعنا نكتب لدينا `reduce` الحل.

 `var arr = <a href='http://www.freecodecamp.com/challenges/symmetric-difference' target='_blank' rel='nofollow'>1, 2, 3, 4, 5, 6]; 
 arr.reduce(function(acc, item){ 
  return acc * item / hcf(acc, item); 
 }, 1); 
` 

أفترض أن وظيفة `hcf()` متاحة في البيئة. اخترت الإدخالات بطريقة ما ؛ يجب أن ترجع `60` كإجابة.

## مزيد من التخفيض

لا يعد الاختصار مجرد وظيفة لتزويدك بالمرافق لحل بعض مشاكل Mathy مثل مجموع الصفيف ، hcf للصفيف ، الحد الأدنى للصفيف الخ.

انها قادرة تماما على الذهاب إلى أبعد الحدود. سوف نتعامل مع بعض الأمثلة المعقدة في الوقت الحالي.

لنفترض أنك تريد تسوية المصفوفات المتداخلة. ونعم ، قبل البدء في القفز إلى أعلى وأسفل في مقعدك - يمكن أن يكون التعشيش أي مستوى تعسفي عميق.

على سبيل المثال ، يمكن أن نأخذ هذا المصفوفة لاختبار الشفرة الخاصة بنا.

 `var arr = [[1, 2, 3], ['cat', 'dog', ['fish', 'bird'], [[[]]]]]; 
` 

يبدو هذا معقدًا بما فيه الكفاية لتبدأ به - صفائف متداخلة ، صفائف متداخلة فارغة بعمق مختلف.

يجب أن يكون الإخراج `[1, 2, 3, 'cat', 'dog', 'fish', 'bird']`

لقد حان الوقت لصياغة استراتيجية. نحن نحتاج بوضوح إلى التمييز بين المصفوفة والعنصر. أيضا ، يجب أن تكون `acc` الصفيف الذي يتم تشكيله أثناء التكرار؛ مما يعني أن القيمة الأولية ستكون صفيفًا فارغًا `[]` .

في جميع أنحاء رمز وظيفة رد الاتصال ، يمكننا ببساطة استخراج المحتوى من `item` ، والذي يمكن أن يكون مجموعة متداخلة بشكل عميق ؛ وكنا `Array.prototype.concat()` مع قيمة `acc` . من الأفضل استخدام `concat()` عبر `Array.prototype.push()` ؛ لأن `push()` يغير المصفوفة الأصلية؛ بينما ينشئ `concat()` مصفوفة جديدة ويعيدها.

وبما أننا لا نعرف مستوى التعشيش في أي لحظة ؛ يجب أن نذهب استدعاء callback المخصصة بشكل متكرر. بمعنى ، علينا أن نكتبه في مكان آخر ونطلق عليه بالاسم داخل `reduce()` .

 `var arr = [[1, 2, 3], ['cat', 'dog', ['fish', 'bird'], [[[]]]]]; 
 
 function flattenArray(arr) { 
  return arr.reduce(function(acc, item){ 
    if(Array.isArray(item)){ 
      return acc.concat(flattenArray(item)); // recursively call to flatten nested array 
    return acc.concat(item); // this does the ordering. If you want reverse ordered output, just reverse it! 
  }, []) 
 
 } 
 
 // call it like this 
 flattenArray(arr); 
` 

بالطبع ، هذا يتطلب بعض الخلفية في وظائف متكررة ؛ ولكن هذا ليس صعبًا للغاية ، مقارنةً بمسألة هذا الطويل!

نعم ، اذهبي واللعب بها. لكن لاحظ كيف يمكننا ببساطة كتابة 3-4 أسطر من الوظائف النظيفة التي تضع بعض الإرشادات البسيطة في الاعتبار - وقم بعمل شيء معقد مثل ذلك الموثوق. هذا قابل للقراءة وصيانته.

على سبيل المثال ، إذا كنت ترغب في تغيير المنطق أو تعديله المنطقي في وقت لاحق (قل إنك تريد وضع بعض الحروف في أعلى السلسلة أو ترميز بعض السلسلة) ؛ يمكنك بسهولة تحديد مكان التغيير. يحدث التعشيش الفعلي داخل `if` الشرط. والطريقة التي استخدمنا بها `reduce` المكالمة هناك - فهي تحافظ على ترتيب العناصر كما هي في الصفيف.

دعونا نأخذ مثالا آخر على ما يبدو معقدا، وجعله على ركبتيها weilding سيف `reduce` !

سنكتشف الاختلافات المتماثلة بين صفحتين أو أكثر. يبدو مروعا ولكن بعد ذلك تبدأ في التفكير.

ماذا ستكون القيمة الأولية؟ بالطبع ، نحن بصدد تشكيل صفيف ؛ لذلك سيكون صفيفًا فارغًا `<a href='https://github.com/reactjs/redux' target='_blank' rel='nofollow'>]` للبدء به. ثم هناك `acc` - لأن حلنا النهائي يحتوي على مصفوفة مختلفة ؛ يجب أن تكون مصفوفة أيضًا. هذا من شأنه الحفاظ على تراكم الخلافات المتماثلة من المصفوفات التي تمت مواجهتها حتى الآن.

فقط ليكون واضحا ، يمكن لهذه الوظيفة قبول عدد عشوائي من المصفوفات. لذلك ، علينا تحويلها كلها إلى صفيف من المصفوفات للتلاعب السهل.

 `function symDiff(args){ 
  // convert args to an Array 
  var argsArray = Array.prototype.slice.call(arguments); 
 
  // now do the reduce magic! 
  argsArray.reduce(function(acc, item){ 
    return acc 
      .filter(function(itemInAcc){ 
        return item.indexOf(itemInAcc) === -1; 
      }) 
      .concat(item.filter(function(itemInItem){ 
        return acc.indexOf(itemInItem) === -1; 
      })); 
  }. []); 
 } 
` 

نعم اعرف. يبدو كبيرا. لذا ، دعونا نرى ما إذا كان بإمكاننا إعادة تشكيلها لجعلها صغيرة. لاحظ أن كلا من `filter` تقوم بنفس العمل ؛ باستثناء مجموعة متغيرة من أزواج الجدل. رائع! دعونا إنشاء وظيفة منفصلة ونطلق عليه مرتين مع تلك الحجج.

 `function symDiff(args){ 
  // convert args to an Array 
  var argsArray = Array.prototype.slice.call(arguments); 
 
  // now do the reduce magic! 
  argsArray.reduce(function(acc, item){ 
    var funWithFiltering = function(arr1, arr2){ 
      return arr1.filter(function(itemInArr1){ 
        return arr2.indexOf(itemInArr1) === -1; 
      }); 
    }; 
 
    return funWithFiltering(acc, item).concat(funWithFiltering(item, acc)); 
  }. []); 
 } 
` 

هذا يبدو أفضل. لكن لا تزال هناك مشكلة أخرى. هذا من شأنه الحفاظ على التكرارات في الصفيف. إذا لم تكن هناك حاجة لذلك ، يمكننا بسهولة كتابة وظيفة أخرى باستخدام `reduce` لإزالة التكرارات.

 `function removeDuplicates(arr){ 
  arr.filter(item, index, self){ 
    // Keep only the first instance of the array, as given by indexOf() 
    // Remove other elements from Array 
    return self.indexOf(item) === index; 
  } 
 } 
` 

لا يمكننا الاستمرار في تجاهل هذا بعد الآن. لقد تم استخدام `filter` حين وعد باستخدام `reduce` ، أليس كذلك؟ والسبب بسيط - يمكن كتابة `filter` مع `reduce` . في الواقع ، أي عملية مجموعة ، من الناحية النظرية ؛ يمكن تنفيذها مع `reduce()` .

هل ستحاول! تنفيذ `map` `filter` مع `reduce` . يجب عليك الاعتناء بالوسائط الاختيارية أيضًا.

## تغليف

قف كان كثيرًا! ولكنني أعتقد أني استخدمت حالة قوية لاستخدام `reduce` كلما أردت استخدام حلقة لإنجازها. تعايش معها مثل طبيعتك الأولى.

بمجرد أن تحصل على مشكلة في بعض التحولات سلسلة أو تلاعب صفيف؛ ابدأ بالكتابة

 `return arr.reduce(function(acc, item){_}, _); 
` 

ثم ملء الفراغات. عندما تستخدم `reduce()` ، فأنت تفكر من حيث تفاعل كل عنصر مع عنصر آخر. أنت تقوم بتكوين الناتج عن طريق الإلحاق به من البداية إلى النهاية.

إطار العمل \[Redux يحتضن مبدأ `reduce` ويحظى بشعبية كبيرة في تصميم الويب.

لاحظ أيضًا ميزة بارزة أخرى - قم `reduce` القوى أو توجيهك لتشكيل الحل دون تغيير أي شيء موجود. على سبيل المثال ، في المثال الأخير ؛ كنا نقوم بالتصفية والتركيب - لكننا كنا نعرف أنه سيعمل كما هو ؛ لأن المجموعة الأولى من العملية لم تغير أيًا من `acc` أو `item` داخل هذا التكرار.

سيكون هذا وقتًا رائعًا `initialValue` ، `initialValue` معلمة `initialValue` [اختيارية](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#Parameters) . لست بحاجة إلى تقديمه بشكل صريح.

إذا حذفت هذا ؛ لأول التكرار `acc` سيكون العنصر الأول في مجموعة، و `item` سيكون البند الثاني في مجموعة. هذا يعني أننا نستطيع أن نكتب مجموعًا من الأدوات المساعدة فقط ، وإهمالها. أو ، لا نحتاج إلى التفكير في `-Infinity` في حالة العثور على قيمة قصوى في الصفيف - ستعمل على ما يرام إذا قمنا بإزالة القيمة الأولية.

ولكن في بعض الحالات المعقدة ، سيكون من الأفضل تصور الحل وصياغةه من حيث بعض القواعد - بعض التهيئة. ومع ذلك ، إذا كنت أكثر راحة بدونها ، لكل واحد خاص به!

إذا كان لديك أي أسئلة أو اقتراحات إضافية ، [فانتقل إلى غرفة الدردشة](https://gitter.im/FreeCodeCamp/FreeCodeCamp) لدينا. وأخبرنا كيف `reduce` !