المسارات
/
jq
jq
/
المنهج
/
الاختزال
ال

الاختزال في jq

تمرينان

نبذة عن الاختزال

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

  • في لغات كثيرة، تُصاغ هذه المسألة على شكل حلقة مع متغير للمراكمة.

  • يمكن كتابة هذه المسألة على شكل دالة تستدعي نفسها. وبلغة شبه الكود، قد يكون لدينا ما يلي.

    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 بالتتابع.
  • تمثّل 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
Note

الدالة 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"]
    
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة

تعلّم الاختزال

التدريب مقفل

افتح 3 تمارين إضافية لممارسة الاختزال