क्या लूप एनोटेशन के लिए इस अतिरिक्त चर का उपयोग करने के कोई लाभ हैं?


11

मैंने एक बड़े प्रोजेक्ट में निम्नलिखित लूप एनोटेशन पाया है जिस पर मैं काम कर रहा हूं (छद्मकोड)

var someOtherArray = [];
for (var i = 0, n = array.length; i < n; i++) {
    someOtherArray[i] = modifyObjetFromArray(array[i]);
}

क्या मेरा ध्यान लाया यह अतिरिक्त "एन" चर है। मैंने पहले कभी इस तरह से लिखे गए लोप के लिए नहीं देखा है।

जाहिर है इस परिदृश्य में कोई कारण नहीं है कि इस कोड को निम्नलिखित तरीके से नहीं लिखा जा सकता है (जो मैं बहुत ज्यादा इस्तेमाल कर रहा हूं):

var someOtherArray = [];
for (var i = 0; i < array.length; i++) {
    someOtherArray[i] = modifyObjetFromArray(array[i]);
}

लेकिन यह मुझे सोच में पड़ गया।

क्या ऐसा कोई परिदृश्य है जब इस तरह के लूप के लिए लिखने से कोई मतलब होगा? यह विचार मन में आता है कि लूप निष्पादन के दौरान "सरणी" की लंबाई बदल सकती है, लेकिन हम मूल आकार से आगे लूप नहीं करना चाहते हैं, लेकिन मैं इस तरह के परिदृश्य की कल्पना नहीं कर सकता।

लूप के अंदर के ऐरे को सिकोड़ने से भी कोई मतलब नहीं है, क्योंकि हमें आउटऑफबाउंड्स अपवाद प्राप्त होने की संभावना है।

क्या एक ज्ञात डिज़ाइन पैटर्न है जहाँ यह एनोटेशन उपयोगी है?

संपादित के रूप में विख्यात @ Jerry101 कारण प्रदर्शन है द्वारा। : यहाँ प्रदर्शन परीक्षण मैं बनाया है के लिए एक लिंक है http://jsperf.com/ninforloop । मेरी राय में अंतर तब तक बहुत बड़ा नहीं है जब तक कि आप एक बहुत बड़ी व्यूह रचना नहीं कर रहे हैं। जिस कोड को मैंने इसे कॉपी किया था, उसमें केवल 20 तत्व तक थे, इसलिए मुझे लगता है कि इस मामले में पठनीयता प्रदर्शन पर विचार करती है।


आपके द्वारा संपादित की गई प्रतिक्रिया में: यह ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग है। मानक array.length तेज और सस्ती है। लेकिन जो भी कारण के लिए, के कार्यान्वयन .length कुछ महंगा करने के लिए बदल सकता है। यदि कोई मान समान रहता है तो उसे कई बार प्राप्त न करें।
पीटर बी

मैं सहमत हूँ। इस विकल्प के बारे में जानना अच्छा है, लेकिन मैं शायद इसे बहुत बार उपयोग नहीं करूंगा, जब तक कि मुझे आपकी sql क्वेरी के समान उदाहरण नहीं मिलता। साभार
व्लाद स्प्रीज़

बात यह है कि, यदि आपकी सरणी एक लाख आइटम है, तो आप array.length को 1 बार के बजाय एक मिलियन बार कॉल करने जा रहे हैं, जबकि मूल्य समान रहता है। एक लाख बार कुछ पूछना और यह जानना कि प्रत्येक बाद का उत्तर पहले उत्तर के समान ही होगा …… बस मुझे कुछ अटपटा सा लगता है।
पीटर बी

1
मुझे नहीं लगता कि यह कोड को पढ़ने में काफी कठिन बनाता है। (गंभीरता से, अगर किसी को इस तरह के एक सरल लूप से परेशानी है, तो उन्हें चिंतित होना चाहिए।) लेकिन: 1) सी और सी-अवरोही भाषाओं के 4 दशकों के बाद, अगर हर गंभीर कंपाइलर ने ऐसा नहीं किया, तो मुझे बहुत आश्चर्य होगा। तुम्हारे लिए; और 2) यह एक गर्म स्थान नहीं हो सकता है। ऐसा लगता है कि जब तक यह लाइब्रेरी के अंदर नहीं है, तब तक कोई व्यक्ति 5 सेकंड अतिरिक्त खर्च करने के लायक नहीं है (उदाहरण के लिए डेटा संरचना का कार्यान्वयन।)
डोभाल

1
C # / में। NET का उपयोग करने वाले वेरिएंट का उपयोग करने वाले वेरिएंट nकी तुलना में धीमी हो सकती है array.Lengthक्योंकि JITTER नोटिस नहीं कर सकता है कि यह सरणी सीमाओं की जाँच को समाप्त कर सकता है।
कोडइन्चोस

जवाबों:


27

चर nयह सुनिश्चित करता है कि उत्पन्न कोड हर पुनरावृत्ति के लिए सरणी लंबाई नहीं लाएगा।

यह एक अनुकूलन है जो इस्तेमाल की गई भाषा के आधार पर रन टाइम में अंतर कर सकता है, चाहे वह सरणी वास्तव में एक संग्रह वस्तु या जावास्क्रिप्ट "सरणी" हो, और अन्य अनुकूलन विवरण।


3
नहीं, यह नहीं है। क्या सरणी की लंबाई हर पुनरावृत्ति में आती है, न केवल भाषा पर निर्भर करती है, बल्कि संकलक और संकलक विकल्पों पर भी और लूप में क्या किया जाता है (मैं सी और सी ++ के बारे में बात कर रहा हूं)
BЈовић

.. और यहां तक ​​कि, मैं व्यक्तिगत रूप से एन असाइनमेंट को लूप के ठीक ऊपर रखूंगा, अगर मैं वास्तव में यह चाहता था, क्योंकि - जैसा कि ओपी ने उल्लेख किया है - यह एक दुर्लभ (वाईएमएमवी) का उपयोग करने के लिए निर्माण है और इसे आसानी से याद किया जाता है / पढ़ने वाले अन्य देवों द्वारा समझा नहीं जाता है कोड।
cwap

20
जैसा कि लिखा गया है, यह nलूप को स्कोप करता है, जो आमतौर पर एक अच्छी बात है। मैं इसे लूप से पहले ही परिभाषित कर दूंगा यदि मैं इसे बाद में फिर से उपयोग करना चाहता हूं।
जेरी १०

4
@ जैरी १०१०: जाहिर तौर पर उदाहरण स्निपेट जावास्क्रिप्ट है, जहां लूप स्कोप जैसी कोई चीज नहीं है ...
बर्गी

1
@ B @овиЈ: व्यवहार में, कंपाइलर शायद ही कभी यह साबित करने के लिए प्रबंधन करता है कि सरणी आकार भिन्न नहीं होता है (आमतौर पर यह केवल तुच्छ साबित होता है यदि आप जिस वेक्टर पर लूपिंग कर रहे हैं वह फ़ंक्शन के लिए स्थानीय है और आप लूप में केवल इनलाइन फ़ंक्शन कॉल कर रहे हैं)।
मट्टियो इटालिया

2

सरणी की लंबाई को प्राप्त करना आसानी से "अधिक महंगा" हो सकता है फिर आप जिस वास्तविक कार्रवाई से अधिक पुनरावृत्त होते हैं।

इसलिए यदि सेट नहीं बदलता है, तो केवल लंबाई को एक बार क्वेरी करें।

सरणियों के साथ नहीं, लेकिन एक sql सर्वर से आने वाले रिकॉर्ड-सेटों के साथ मैंने प्रत्येक पुनरावृत्ति को रिकॉर्ड नहीं करते हुए नाटकीय सुधार देखा है। (निश्चित रूप से ऐसा तभी करें जब आप गारंटी दे सकते हैं कि आप इस प्रक्रिया के दौरान सरणी या रिकॉर्ड-सेट परिवर्तित नहीं हुए हैं)।


अगर रिकॉर्ड की गिनती बदलती है, तो क्या? कहते हैं कि 100 आइटम थे, और जब आप आइटम 50 प्रसंस्करण कर रहे हैं, # 25 डालने के बाद एक आइटम। इसलिए जब आप आइटम # 51 संसाधित करते हैं, तो यह # 50 के समान है जिसे आपने पहले ही संसाधित किया है, और चीजें गलत हो जाती हैं। तो समस्या यह नहीं है कि लंबाई बदलती है, यह बहुत अधिक व्यापक है।
gnasher729

@ gnasher729 एक बार असममित व्यवहार में आने के बाद बहुत कुछ गलत हो सकता है। लेकिन वहाँ चीजें हैं जो आप के खिलाफ कर सकते हैं जैसे शुरू और sql लेनदेन।
Pieter B

2

यह विचार मन में आता है कि लूप निष्पादन के दौरान "सरणी" की लंबाई बदल सकती है, लेकिन हम मूल आकार से आगे लूप नहीं करना चाहते हैं, लेकिन मैं इस तरह के परिदृश्य की कल्पना नहीं कर सकता।

प्रदर्शन के बारे में बात करने वाले लोग शायद सही हैं कि यह इस तरह से लिखा गया है (जिस व्यक्ति ने इसे लिखा है वह सही नहीं हो सकता है कि यह प्रदर्शन को काफी प्रभावित करता है, लेकिन यह एक और मामला है)।

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

guests = [];
for (i = 0; i < invitations.length; ++i) {
    if (! invitations[i].is_declined()) {
        guests.append(invitations[i].recipient())
    }
}
// maybe some other stuff to modify the guestlist
for (i = 0, n = guests.length; i < n; ++i) {
    if (guests[i].has_plus_one()) {
        guests.append(guests[i].get_plus_one());
    }
}

बेशक इसे लिखने के अन्य तरीके हैं। इस मामले में, मैं एक ही समय में प्लस लोगों के लिए जाँच कर सकता था कि क्या प्राप्तकर्ता ने उनके निमंत्रण स्वीकार किए हैं, और एक बार में पूर्ण अतिथि सूची एक आमंत्रण का उत्पादन किया था। मैं जरूरी नहीं कि उन दो ऑपरेशनों को संयोजित करना चाहता हूं, लेकिन मैं तुरंत एक कारण नहीं सोच सकता कि यह निश्चित रूप से गलत क्यों है और इसलिए इस डिजाइन की आवश्यकता है । यह कभी-कभी विचार करने का एक विकल्प है।

वास्तव में मुझे लगता है कि इस कोड के साथ सबसे गलत बात यह है कि guestsसरणी की सदस्यता का मतलब कोड में विभिन्न बिंदुओं पर अलग-अलग चीजें हैं। इसलिए मैं निश्चित रूप से इसे एक "पैटर्न" नहीं कहूंगा, लेकिन मैं नहीं जानता कि यह इस दोष के बारे में कभी भी कुछ भी करने के लिए पर्याप्त नहीं है


ऐरे को दूसरे धागे से भी संशोधित किया जा सकता है। यह संकलक को लंबाई पुनर्प्राप्ति को अनुकूलित करने से रोकता है। तो सवाल में, प्रोग्रामर ने स्पष्ट रूप से कहा कि अन्य थ्रेड्स में भी सरणी नहीं बदलती है।
बसिलेव्स

0

यदि संभव हो तो, आपको एक पुनरावृत्त का उपयोग करना चाहिए जो कि सरणी के सभी तत्वों का पता लगाता है। आप सरणी का उपयोग केवल एक अनुक्रम के रूप में करते हैं, यादृच्छिक-अभिगम भंडारण के रूप में नहीं, इसलिए यह स्पष्ट होगा कि एक पुनरावृत्ति करने वाला जो क्रमिक पहुंच को पूरा करता है वह तेजी से होगा। कल्पना कीजिए कि आपको क्या लगता है कि एक सरणी वास्तव में एक द्विआधारी वृक्ष है, लेकिन किसी ने कोड लिखा है जो तत्वों की गणना करके "लंबाई" निर्धारित करता है, और कोड जो i-th तत्व तक पहुंचता है, तत्व को भी पीछे छोड़ता है, प्रत्येक में ओ (एन) )। एक पुनरावृत्ति बहुत तेज हो सकती है, आपका लूप स्लोवू होगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.