ধরা যাক, আমরা সংখ্যার একটি অ্যারে যোগ করতে চাই। এই লক্ষ্য পূরণের অনেক উপায় আছে।
অনেক ভাষায় এই সমস্যাটি একটি অ্যাকুমুলেটর ভ্যারিয়েবলসহ একটি লুপ হিসেবে প্রকাশ করা হয়।
এই সমস্যাটি একটি রিকার্সিভ ফাংশন হিসেবে লেখা যায়। সিউডো-কোডে এটি দেখতে এমন হতে পারে।
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"]
আপনি একজন শিক্ষক। বছরের শেষে, আপনি আপনার প্রতিটি শিক্ষার্থীর জন্য একটি সংখ্যাসূচক গ্রেড তৈরি করেছেন। এখন আপনাকে সেটিকে একটি লেটার গ্রেডে রূপান্তর করতে হবে এবং কতজন শিক্ষার্থী কোন লেটার গ্রেড পেয়েছে তা গুনতে হবে।
letter_grade ফাংশনটি ইনপুট হিসেবে একটি সংখ্যাসূচক গ্রেড নেবে, এবং আউটপুট হিসেবে লেটারটি দেবে।
এই রেঞ্জগুলো ব্যবহার করুন:
| লেটার | গ্রেড |
|---|---|
| A | 90% - 100% |
| B | 80% - 89% |
| C | 70% - 79% |
| D | 60% - 69% |
| F | 0% - 59% |
উদাহরণ:
75 | letter_grade # => "C"
count_letter_grades ফাংশনটি শিক্ষার্থীদের নাম থেকে তাদের গ্রেডে ম্যাপ করা একটি অবজেক্ট নেবে।
আউটপুট হবে প্রতিটি লেটার গ্রেড থেকে সেই গ্রেড পাওয়া শিক্ষার্থীর সংখ্যায় ম্যাপ করা একটি অবজেক্ট।
উদাহরণ:
{"Joe": 78, "Jane": 93, "Richard": 72} | count_letter_grades
# => {"A": 1, "B": 0, "C": 2, "D": 0, "F": 0}
এটি সমাধান করার কয়েকটি ভিন্ন উপায় আছে।
অনুশীলনের জন্য reduce ফিল্টারটি ব্যবহার করুন।
Exercism-এ সাইন আপ করুন, jq ট্র্যাকের 12টি কনসেপ্ট75টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।