मैंने एक स्ट्रिंग एस को उलटने के लिए अपने आप पर एक पुनरावर्ती समाधान खोजने की कोशिश की लेकिन यह स्ट्रिंग्स> 1 चार के लिए 'अपरिभाषित' देता है। क्या कोई कृपया मुझे इसे डीबग करने में मदद कर सकता है? मुझे पता है कि यह शानदार तरीका नहीं है, लेकिन त्रुटि खोजने से मुझे आगे बढ़ने में मदद मिल सकती है।
बहुत बहुत धन्यवाद!
var revFunc = function (s, r, n, i) {
if (i > n) {
return r;
}
r = r + s[n - i];
i++;
revFunc(s, r, n, i);
};
var reverse = function (s) {
var r = "";
var n = s.length - 1;
var i = 0;
if (n < 1) {
return s;
}
return revFunc(s, r, n, i);
};
3 जवाब
रिकर्सन के लिए उपयुक्त नहीं है
जबकि पहले से प्रस्तुत किया गया मामूली सुधार आपके कार्य को ठीक करता है, मैं सुझाव देना चाहता हूं कि यह संस्करण रिकर्सन के बारे में गलतफहमी दिखाता है।
आपका फ़ंक्शन रिकर्सन का उपयोग यह अपडेट करने के लिए कर रहा है कि अन्यथा थोड़ी देर में स्थानीय चर क्या होंगे। इसे इस तरह फिर से लिखा जा सकता है:
var reverse = function (s) {
var r = "";
var n = s.length - 1;
var i = 0;
if (n < 1) {
return s;
}
while (i <= n) {
r = r + s[n - i]
i++
}
return r
};
console .log (reverse ('abcde'))
आपके द्वारा उपयोग किया जाने वाला रिकर्सन उसी कोड को लिखने का एक और माध्यम है।
रिकर्सन कुछ अलग के लिए है। हम चाहते हैं कि हमारे एल्गोरिदम हमारी डेटा संरचनाओं से मेल खाते हों। रिकर्सन के लिए वास्तव में सार्थक होने के लिए, हमें इसे पुनरावर्ती डेटा संरचना पर उपयोग करना चाहिए।
लेकिन हम इस समस्या के लिए ऐसा कर सकते हैं कर सकते हैं।
एक स्ट्रिंग के बारे में बार-बार सोचना
एकल डेटा संरचना के बारे में सोचने के लिए अक्सर कई अलग-अलग तरीके होते हैं। हम एक स्ट्रिंग को एक पुनरावर्ती संरचना के रूप में इस तरह से सोच सकते हैं:
एक स्ट्रिंग या तो है
- खाली स्ट्रिंग, "", या
- एक वर्ण जिसके बाद एक स्ट्रिंग होती है
हम एक गैर-रिक्त स्ट्रिंग के दो भागों को head
और tail
कह सकते हैं।
पुनरावर्ती एल्गोरिदम में पुनरावर्ती परिभाषा का उपयोग करना
उस फॉर्मूलेशन के साथ, हम एक रिकर्सिव एल्गोरिदम लिख सकते हैं जो संरचना से मेल खाता है:
एक स्ट्रिंग का उत्क्रमण या तो है
- खाली स्ट्रिंग का उलटा (जो अभी भी खाली स्ट्रिंग है), या
- पूंछ का उलटा, उसके बाद सिर
तब कोड व्यावहारिक रूप से खुद को लिखता है:
const reverse = (string) =>
string .length == 0
? ""
: reverse (string .slice (1)) + string[0]
console .log (reverse ('abcdefg'))
वेरिएंट
इसमें निश्चित रूप से भिन्नताएं संभव हैं। जब जेएस वातावरण में पूंछ-कॉल-अनुकूलन अंततः आम है, तो हम तैयार रहना चाहते हैं, और इसे पूंछ-पुनरावर्ती संस्करण में बदल सकते हैं, जैसे कुछ
const reverse = (string, result = "") =>
string .length == 0
? result
: reverse (string .slice (1), string [0] + result)
(ध्यान दें कि इस शैली के साथ एक संभावित समस्या है। कुछ संदर्भों में फ़ंक्शन का उपयोग करने के तरीके में डिफ़ॉल्ट पैरामीटर आ सकते हैं। उदाहरण के लिए, आप इस संस्करण के साथ strings .map (reverse)
को सफलतापूर्वक कॉल नहीं कर सकते हैं। आप इसे विभाजित करके कर सकते हैं यह एक सहायक कार्य और एक मुख्य कार्य में है, लेकिन यह हमें दूर ले जा रहा है।)
या, इस तथ्य का लाभ उठाते हुए कि तार चलने योग्य हैं, हम डिफ़ॉल्ट मान के साथ-साथ पैरामीटर विनाश का उपयोग करके एक अच्छी तरह से सरल संस्करण लिख सकते हैं:
const reverse = ([head = undefined, ...tail]) =>
head == undefined
? ""
: reverse (tail) + head
रिकर्सन के लाभ
और उससे कहीं अधिक सरल होने की कल्पना करना कठिन है। यह संस्करण एल्गोरिथम को काफी सीधे कैप्चर करता है। और एल्गोरिथम डेटा संरचना के हमारे विवरण से स्पष्ट रूप से जुड़ा हुआ है।
एक बात पर ध्यान दें कि इनमें से कोई भी फ़ंक्शन उपयोग नहीं करता है: स्थानीय चर। साधारण रिकर्सन अक्सर इस तरह से लिखा जा सकता है कि उनकी कोई आवश्यकता नहीं है। यह एक प्रमुख आशीर्वाद है, क्योंकि इसका मतलब है कि परिवर्तनशील अवस्था के छिपने के लिए कोई जगह नहीं है। और परिवर्तनीय स्थिति कई, कई प्रोग्रामिंग त्रुटियों का स्रोत है।
आप return
को भूल गए
return revFunc(s, r, n, i);
अपडेट किया गया:
var revFunc = function (s, r, n, i) {
if (i > n) {
return r;
}
r = r + s[n - i];
i++;
return revFunc(s, r, n, i);
};
सुझाव: कृपया चर के लिए बेहतर नाम का उपयोग करें, यह बेकार है s,r,n,i
क्या आप एक सरल उपाय आजमा सकते हैं:
let str = "hello";
let reverse_str = str.split("").reverse().join("");
return revFunc(s, r, n, i);