संचालन जानबूझकर सममित नहीं हैं। सूची डेटा संरचना एक सिंगल-लिंक्ड सूची है जहां प्रत्येक नोड (डेटा और पॉइंटर दोनों) अपरिवर्तनीय हैं। इस डेटा संरचना के पीछे विचार यह है कि आप आंतरिक नोड्स के संदर्भ ले कर सूची के मोर्चे पर संशोधन करते हैं और उन्हें इंगित करने वाले नए नोड्स जोड़ते हैं - सूची के विभिन्न संस्करण सूची के अंत के लिए समान नोड्स साझा करेंगे।
:::
ऑपरेटर जो सूची के अंत में एक नया तत्व जोड़ता है उसे पूरी सूची की एक नई प्रतिलिपि बनाना है, अन्यथा यह उन अन्य सूचियों को संशोधित करेगा जो आपके द्वारा संलग्न की जा रही सूची के साथ नोड साझा करते हैं। यही कारण है कि :::
रैखिक समय लेता है। स्कैला में एक डेटा संरचना है जिसे ListBuffer
कहा जाता है जिसे आप :::
ऑपरेटर के बजाय एक सूची के अंत में तेजी से जोड़ने के लिए उपयोग कर सकते हैं। असल में, आप एक नया ListBuffer
बनाते हैं और यह एक खाली सूची से शुरू होता है। ListBuffer
प्रोग्राम को किसी भी अन्य सूची से पूरी तरह से अलग सूची बनाए रखता है, इसलिए अंत में जोड़कर इसे संशोधित करना सुरक्षित है। जब आप अंत में जोड़ना समाप्त कर लेंगे, तो आप ListBuffer.toList
पर कॉल करें, जो दुनिया में सूची जारी करता है, जिस बिंदु पर आप इसे कॉपी किए बिना अंत में जोड़ सकते हैं।
foldLeft
और foldRight
भी एक समान असमानता साझा करते हैं। foldRight
आपको सूची के अंत तक पहुंचने के लिए पूरी सूची में जाने की आवश्यकता है, और वहां आप जिस तरह से गए हैं, उसका ट्रैक रखें, ताकि आप उन्हें रिवर्स ऑर्डर में देख सकें। यह आमतौर पर बार-बार किया जाता है, और इससे foldRight
तक बड़ी सूचियों पर स्टैक ओवरफ्लो हो सकता है। दूसरी तरफ foldLeft
, सूची में दिखाई देने वाले क्रम में नोड्स से संबंधित है, इसलिए यह उन लोगों को भूल सकता है जिन्हें पहले से देखा गया है और केवल एक समय में एक नोड के बारे में जानना आवश्यक है। हालांकि foldLeft
भी आम तौर पर रिकर्सिवली कार्यान्वित किया जाता है, यह एक अनुकूलन कहा पूंछ प्रत्यावर्तन उन्मूलन, जिसमें संकलक एक पाश में पुनरावर्ती कॉल बदल देती समारोह पुनरावर्ती कॉल से लौटने के बाद कुछ भी नहीं है, क्योंकि का लाभ ले सकते। इस प्रकार, foldLeft
बहुत लंबी सूचियों पर भी ढेर को ओवरफ़्लो नहीं करता है। EDIT: foldRight
स्कैला 2 में।8 वास्तव में सूची को उलटकर और foldLeft
को उलट सूची पर चलाकर कार्यान्वित किया जाता है - इसलिए पूंछ रिकर्सन मुद्दा कोई मुद्दा नहीं है - दोनों डेटा संरचनाएं पूंछ रिकर्सन को सही ढंग से अनुकूलित करती हैं, और आप या तो एक चुन सकते हैं (अब आप इस मुद्दे में शामिल हैं कि आप reverse
reverse
के संदर्भ में परिभाषित कर रहे हैं - यदि आप अपने अपने इसके मजे के लिए रिवर्स विधि को परिभाषित कर रहे हैं, तो आपको चिंता करने की आवश्यकता नहीं है, लेकिन अगर आप थे तो फ़ोल्ड राइट विकल्प नहीं होगा स्काला के रिवर्स विधि को परिभाषित।)
इस प्रकार, आप foldRight
और :::
से अधिक foldLeft
और ::
को प्राथमिकता देनी चाहिए।
(। एक एल्गोरिथ्म है कि ::
साथ :::
या foldRight
साथ foldLeft
गठबंधन आरंभ करेगा, तो आप अपने लिए एक निर्णय करने के लिए के बारे में जो ज्यादा महत्वपूर्ण है की जरूरत है:। स्टैक स्थान या समय से चल रहा है या आप एक ListBuffer
साथ foldLeft
का उपयोग करना चाहिए)
स्रोत
2010-06-27 16:01:23
** ऊपर 'foldRight' का आरोपण ** ** स्कैला 2.8 के लिए मानक लाइब्रेरी में से एक है। Https: //lampsvn.epfl देखें।ch/trac/scala/browser/scala/trunk/src /// लाइब्रेरी/स्कैला/संग्रह/TraversableOnce.scala # L194 –
नहीं, यह नहीं है। https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/library/scala/collection/LinearSeqOptimized.scala#L129 – Apocalisp
बहुत बहुत धन्यवाद! लेकिन मेरे पास एक (थोड़ा स्पर्शपूर्ण) प्रश्न है - आप कैसे कहते हैं कि यह कार्यान्वयन मानक पुस्तकालय में से एक से तेज है? मैंने अतीत में ऐसा कुछ करने की कोशिश की है, लेकिन बुरी तरह से निर्मित परीक्षणों और जेवीएम वार्मअप मुद्दों से जला दिया गया है। लिंक, संसाधन सहायक होंगे। उस ने कहा, मैं foldLeft के पक्ष में foldRight से परहेज करने के इच्छुक हूँ। –