2017-04-22 12 views
10

मैं this Codewars challenge का प्रयास कर रहा था और समस्या में किसी संख्या के विभाजक ढूंढने और फिर इन divisors वर्ग के योग की गणना शामिल है। मुझे इस समस्या के दो दृष्टिकोण मिले।जावास्क्रिप्ट प्रदर्शन:() बनाम फॉर-लूप

पहले दृष्टिकोण finding the sum of all divisors के बारे में एक और Stackoverflow प्रश्नों पर आधारित है और पहली बार में चालाक लगता है:

function divisorsSquared(n) { 
    // create a numeric sequence and then reduce it 
    return [...Array(n+1).keys()].slice(1) 
    .reduce((sum, num)=>sum+(!(n % (num)) && Math.pow(num,2)), 0); 
} 

दूसरा दृष्टिकोण मैं एक साधारण के लिए लूप उपयोग कर रहा था इस्तेमाल किया:

function divisorsSquared(n) { 
    var sum = 0; 
    for(var i = 1; i<= n; i++){ 
    if(n % i === 0) sum += Math.pow(i,2); 
    } 
    return sum; 
} 

अब मैं ध्यान दिया कि पहला दृष्टिकोण दूसरे की तुलना में काफी धीमी है और एक त्वरित jsperf test इसकी पुष्टि करता है।

मेरे प्रश्न हैं: पहला दृष्टिकोण इतना धीमा क्यों है और उत्पादन कोड में कौन सा दृष्टिकोण बेहतर है?

कोडेवार्स पर मुझे पता है कि कई चुनौतियों के लिए समान सरणी विधियों का उपयोग करके चालाक एक-लाइन समाधान हैं। शुरुआत के रूप में, क्या ऐसे समाधानों को फॉर-लूप की तुलना में बेहतर अभ्यास माना जा सकता है, भले ही प्रदर्शन खराब हो?

+5

आप कोड को देखो, तो पहले एक एक निर्माता दोहराता दोहराता दोहराता का उपयोग करता है, तो प्रसार करने के लिए है, तो कुंजी प्राप्त करने के लिए, तो काट करने के लिए ... दूसरा एक बार फिर से ... – adeneo

+0

मैंने इसके बारे में नहीं सोचा था, लेकिन अब यह बहुत स्पष्ट लगता है। धन्यवाद! –

उत्तर

2

कार्यात्मक या अनिवार्य दृष्टिकोण जेएस में एक फर्क पड़ता है। इंपीरेटिव हमेशा जीतता है। फिर भी, असली बात यह है कि अधिकतर समय एक बेहतर एल्गोरिदम विजेता होता है। आपका कोड एक बेवकूफ दृष्टिकोण है। लक्ष्य लक्ष्य के वर्ग रूट तक पूर्णांक को जांचकर आप इसे बेहतर तरीके से काम करने के लिए ट्यून कर सकते हैं और आपको प्रति चेक दो जवाब मिलेंगे। यदि लक्ष्य 100 है तो 2 लाभांश है तो 100/2 लाभांश भी होना चाहिए .. इसलिए Math.sqrt(100) - 1 पर जांच करना उचित है और इसे दो बार नहीं मानने के लिए देखभाल के साथ 10 को संभालना उचित है।

तदनुसार अब कम से कम कार्यात्मक समाधान अनिवार्य निष्क्रिय समाधान को धड़कता है। , तो दोहराता कम करने के लिए

function divisorsSquared(n) { 
 
    var sn = Math.sqrt(n); 
 
    return Array.from({length:~~sn-1},(_,i) => i+1) 
 
       .reduce((s,m) => n%m ? s : s + m*m + (n/m)*(n/m), 0) + (n%sn ? 0 : sn*sn); 
 
} 
 
var result = 0; 
 
console.time("functional and tuned"); 
 
result = divisorsSquared(1000000); 
 
console.timeEnd("functional and tuned"); 
 
console.log("for input: 1000000 the result is:",result); 
 

 

 
function dvssqr(n) { 
 
    var sum = 0; 
 
    for(var i = 1; i<= n; i++){ 
 
    if(n % i === 0) sum += Math.pow(i,2); 
 
    } 
 
    return sum; 
 
} 
 

 
console.time("imperative and naive"); 
 
result = dvssqr(1000000); 
 
console.timeEnd("imperative and naive"); 
 
console.log("for input: 1000000 the result is:",result);

4
  • Array(n+1) n + 1 तत्वों के साथ एक सरणी, Array(n+1).keys() बनाया सरणी के सूचकांक पर एक इटरेटर रिटर्न आबंटित करता है, लेकिन प्रसार ऑपरेटर [...Iterator] में मदद करता है "खोलने" अभी तक एक सरणी में इस इटरेटर, तो अंत में slice(1) कॉपी करने के लिए साथ आता है दूसरी बार इंडेक्स 1 से शुरू होने वाला सरणी बनाया गया जो 0 नंबर के साथ एक और सरणी (तीसरा एक) आवंटित करता है। तो वे 3 आवंटन थे लेकिन 2 डिक्टेड थे। आपका for-loop किसी भी सरणियों का आवंटन नहीं है, यह i और sum के लिए केवल 2 आवंटन के साथ हे (एन) में एक साधारण ट्रेवर्सल है, इसलिए इसे और अधिक कुशल
  • sum+(!(n % (num)) && Math.pow(num,2)) अनिवार्य रूप से if(n % i === 0) sum += Math.pow(i,2); रूप में ही है लेकिन if दृष्टिकोण रास्ता अधिक पठनीय है । अगर मैं जज था, तो मैं दूसरा दृष्टिकोण चुनूंगा क्योंकि यह अधिक मेमोरी कुशल है, फिर भी यह पठनीयता का पक्ष लेता है।
2

कोड में देख रहे हैं, क्योंकि लूप स्पष्ट रूप से कम जटिल और अधिक पठनीय है।

विचार करें कि आप एक टीम के भीतर काम कर रहे हैं, आपके टीम के सदस्यों की अधिकतम संख्या पता चलेगी कि कोड तुरंत क्या कर रहा है। कुछ को देखना होगा कि reduce() विधि क्या है, लेकिन फिर वे यह भी जान लेंगे कि क्या हो रहा है। तो यहां, दूसरों के पढ़ने और समझने के लिए एक लूप आसान है।

दूसरी ओर, देशी सरणी कार्यों (filter(), map(), reduce()) कुछ अतिरिक्त कोड और भी प्रदर्शन में धीमी लिखने से आप बचत होगी।

शुरुआत के लिए, मुझे लगता है कि फॉर-लूप देशी सरणी कार्यों पर बेहतर होना चाहिए।

संबंधित मुद्दे