2011-03-07 13 views
15

मान लीजिए मैं एक iterator है:एक पुनरावर्तक कैसे क्लोन करें?

val it = List("a","b","c").iterator 

मैं इसकी एक प्रति चाहते हैं; मेरे कोड है:

val it2 = it.toList.iterator 

यह सही है, लेकिन अच्छा नहीं लग रहा है। क्या ऐसा करने के लिए कोई अन्य एपीआई है?

+0

क्यों? एक बार जब आप इसे क्लोन कर लेंगे तो मूल इटरेटर का उपभोग किया जाएगा और बेकार होगा, इस प्रकार पहले क्लोन के पूरे बिंदु को हराया जाएगा ... –

+2

@ केविन, यह निश्चित रूप से मामला नहीं है, निश्चित रूप से? जाहिर है, ऐसा लगता है कि एक ऐसा ऑपरेशन हो सकता है जो मुझे एक इटरेटर प्रदान करता है जो स्रोत अनुक्रमक के समान अनुक्रम लौटाएगा - बेशक, राज्य के मुद्दे सभी इटरेटर के लिए असंभव बना सकते हैं। ऐसा लगता है कि मूल रूप से स्रोत को उपभोग करने की आवश्यकता नहीं है। –

+0

'val' से' def' तक स्विच करने से आपको हर बार प्रतीक का संदर्भ देने के लिए एक नया इटरेटर मिल जाएगा (उपरोक्त उदाहरण में 'it' नाम दिया गया है)। कई मामलों में इस तरह से आसान लग सकता है। – matanster

उत्तर

9

चेतावनी: स्काला 2.9.0 के रूप में, कम से कम, इस मूल इटरेटर खाली हो जाती है। आप दो प्रतियां प्राप्त करने के लिएval ls = it.toList; val it1 = ls.iterator; val it2 = ls.iteratorकर सकते हैं। या डुप्लिकेट का उपयोग करें (जो गैर-सूचियों के लिए भी काम करता है)।

रेक्स के जवाब किताब से है, लेकिन वास्तव में अपने मूल समाधान अब तक scala.collection.immutable.List के लिए सबसे कुशल कर रहा है।

सूची इटरेटर्स को उस तंत्र का उपयोग करके डुप्लिकेट किया जा सकता है, अनिवार्य रूप से कोई ओवरहेड नहीं। यह scala.collection.immutable.LinearSeq, esp में iterator() के कार्यान्वयन की त्वरित समीक्षा द्वारा पुष्टि की जा सकती है। टूलीस्ट विधि की परिभाषा, जो बैकिंग सेक के _.Listist को वापस लौटाती है, यदि यह एक सूची है (जैसा कि यह आपके मामले में है) पहचान है।

मुझे आपके प्रश्न की जांच करने से पहले सूची इटरेटर्स की इस संपत्ति से अवगत नहीं था, और मैं जानकारी के लिए बहुत आभारी हूं ... अन्य चीजों के साथ इसका मतलब है कि कई "सूची कंकड़" एल्गोरिदम को स्कैला पर कुशलतापूर्वक कार्यान्वित किया जा सकता है अपरिवर्तनीय इटरेटर का उपयोग कंकड़ के रूप में करते हैं।

+0

मेरी इच्छा है कि मैं टिप्पणियों के साथ-साथ प्रश्नों को भी पसंदीदा कर सकूं, क्योंकि आप एक उत्कृष्ट उपयोग केस/पॉइंट बढ़ाते हैं। –

+0

संबंधित पोस्ट: http: // stackoverflow।com/प्रश्न/16380592/spec2 ब्रेक-मेरी-परीक्षण-डेटा-कारण-टू-तरह यह काम करता है-के साथ-इटरेटर – ses

17

जिस विधि को आप ढूंढ रहे हैं वह duplicate है।

scala> val it = List("a","b","c").iterator 
it: Iterator[java.lang.String] = non-empty iterator 

scala> val (it1,it2) = it.duplicate 
it1: Iterator[java.lang.String] = non-empty iterator 
it2: Iterator[java.lang.String] = non-empty iterator 

scala> it1.length 
res11: Int = 3 

scala> it2.mkString 
res12: String = abc 
+3

चेतावनी: यह इटरेटर्स के बीच अंतर को कैश करने के लिए एक परिवर्तनीय 'कतार' का उपयोग करता है, जो अप्रत्याशित स्मृति समस्याओं का कारण बन सकता है। साथ ही, 'अगली' और 'हैक्स्टक्स्ट' नए इटरेटर्स के लिए 'सिंक्रनाइज़' हैं, जो उन्हें सामान्य इटरेटर्स की तुलना में बहुत धीमी बनाती हैं। –

+3

एक और चेतावनी: जबकि 'it1' और' it2' स्वतंत्र रूप से उपयोग किया जा सकता है, 'it.next' को दोनों डुप्लिकेट को आगे बढ़ाकर! साथ ही, डुप्लिकेट 'वर्तमान' तत्व से शुरू होता है, सूची की शुरुआत नहीं। दुख की बात है, 'डुप्लिकेट' विशेष रूप से बुरी तरह से दस्तावेज है। – Raphael

+2

चेतावनी दी गई। वे महसूस करने के लिए महत्वपूर्ण हैं, लेकिन यदि आप जो भी पूछ रहे हैं उसके बारे में सावधानीपूर्वक सोचते हैं तो भी "स्वयं स्पष्ट" हैं: बेशक, यदि आपके पास एक इटरेटर है और आप दो चाहते हैं जो सिंक में नहीं हैं, तो आप जा रहे हैं किसी प्रकार के भंडारण की आवश्यकता है, आप केवल उस स्थान से शुरू कर सकते हैं जहां आप हैं और खोए हुए शुरुआत में वापस नहीं जाते हैं, और यदि आप सिर्फ _everything_ की प्रतिलिपि नहीं ले रहे हैं तो आपको यह पता लगाने के लिए सिंक्रनाइज़ेशन की आवश्यकता होगी कि पीछे क्या छोड़ा गया है दोनों इटरेटर्स और पकड़ने के लिए तैयार है। –

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