لنفترض أننا نريد جمع مصفوفة من الأعداد. توجد طرق كثيرة لتحقيق هذا الهدف.
في لغات كثيرة، تُصاغ هذه المسألة على شكل حلقة مع متغير للمراكمة.
يمكن كتابة هذه المسألة على شكل دالة تستدعي نفسها. وبلغة شبه الكود، قد يكون لدينا ما يلي.
function Add(X, Sum=0):
if X is empty then
return Sum
else
return Add(rest(X), Sum + first(X))
end
end
ويمكن أيضًا وصف هذه الطريقة في تقسيم المسألة إلى أجزاء أصغر بأنها «الاختزال باتجاه الحالة الأساسية».
reduce أسلوب لدمج كل عناصر بنية بيانات في قيمة واحدة.
تمرّ هذه العملية على بنية البيانات عنصرًا عنصرًا، وتطبّق دالة على كل عنصر لتحديث النتيجة المتراكمة.
في jq، تُنفَّذ هذه العملية عبر المرشّح reduce.
وفي لغات أخرى، قد يُسمّى «fold» أو «fold-left» أو «inject» أو «aggregate».
ويبدو تعبير reduce في jq هكذا.
reduce STREAM_EXPRESSION as $var (INITIAL_VALUE; UPDATE_EXPRESSION)
STREAM_EXPRESSION هو تيّار من العناصر، يُخزَّن كل منها في المتغير $var بالتتابع.
.[]: $myArray | .[].INITIAL_VALUE القيمة الابتدائية للنتيجة المتراكمة (وتُعرف باسم «المُراكِم»).UPDATE_EXPRESSION («يطوي») القيمة الحالية ($var) في المُراكِم.
. قيمة المُراكِم.reduce.لنلقِ نظرة على مثال: جمع الأعداد في مصفوفة.
المرشّح add يقوم بذلك بالضبط، لكننا سنرى كيف ننفّذه.
إذا استخدمنا [10, 20, 30, 40] مدخلًا، واتخذنا صفرًا حالةً ابتدائية، فهكذا تبدو كل خطوة.
| # | الحالة | العنصر | الاختزال | النتيجة |
|---|---|---|---|---|
| 1 | 0 | 10 | 0 + 10 | 10 |
| 2 | 10 | 20 | 10 + 20 | 30 |
| 3 | 30 | 30 | 30 + 30 | 60 |
| 4 | 60 | 40 | 60 + 40 | 100 |
وبصيغة jq، يبدو ذلك كما في الكود التالي.
0 + 10 | . + 20 | . + 30 | . + 40
ويمكننا التعبير عن ذلك بالمرشّح reduce.
[10, 20, 30, 40] | reduce .[] as $n (0; . + $n) # => 100
الدالة add المدمجة منفَّذة فعليًا بـ reduce، لكنها تستخدم null كحالة ابتدائية (إذ يمكن جمع أي نوع بيانات مع null).
def add: reduce .[] as $x (null; . + $x);
في تعبير الاختزال، تمثّل . المُراكِم.
وإذا كان المدخل كائنًا تحتاج إلى الرجوع إليه داخل دالة الاختزال، فيجب تخزينه في متغير.
{"apple": 10, "banana": 16, "carrot": 4}
| . as $obj
| reduce (keys | .[]) as $key (0; . + $obj[$key]) # => 30
يمكن أن يكون المُراكِم من أي نوع من البيانات. فمثلًا، قد ترغب في عكس ترتيب مصفوفة.
["A", "B", "C", "D"]
| reduce .[] as $elem ([]; [$elem] + .) # => ["D", "C", "B", "A"]