मान लीजिए हमें संख्याओं के एक ऐरे का जोड़ निकालना है। यह काम करने के कई तरीके हैं।
कई भाषाओं में यह समस्या एक लूप और एक एक्युमुलेटर वेरिएबल के रूप में लिखी जाती है।
यह समस्या एक रिकर्सिव फंक्शन के रूप में भी लिखी जा सकती है। स्यूडो कोड में यह कुछ ऐसा दिखेगा।
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 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।