ধরা যাক, আমরা সংখ্যার একটি অ্যারে যোগ করতে চাই। এই লক্ষ্য পূরণের অনেক উপায় আছে।
অনেক ভাষায় এই সমস্যাটি একটি অ্যাকুমুলেটর ভ্যারিয়েবলসহ লুপ হিসেবে লেখা হয়।
এই সমস্যাটি একটি রিকার্সিভ ফাংশন হিসেবেও লেখা যায়। সিউডো-কোডে সেটি এমন হতে পারে।
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" বলা হতে পারে।
jq-এর reduce এক্সপ্রেশনটি দেখতে এমন।
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"]