2012-11-26 29 views
5

में एक इटरेटर के माध्यम से पुनरावृत्ति करने का सबसे तेज़ तरीका क्या है, मान लीजिए कि मैं एक सामान्य संकेतक के माध्यम से पुनरावृत्ति के माध्यम से पुनरावृत्ति करना चाहता हूं, बिना इटेटर के आंतरिक के बारे में जानना और अनिवार्य रूप से बिना किसी जादू के जादू के माध्यम से धोखा देना और यह मानना किसी भी प्रकार का पुनरावर्तनीय, जो एक पुनरावर्तक की सेवा करता है; क्या हम रनटाइम पर या मैक्रोज़ के माध्यम से एक इटरेटर के रिवर्स को अनुकूलित कर सकते हैं?रिवर्स

आगे

var a = [1, 2, 3, 4].iterator(); 
// Actual iteration bellow 
for(i in a) { 
    trace(i); 
} 

पिछड़ों

var a = [1, 2, 3, 4].iterator(); 
// Actual reverse iteration bellow 
var s = []; 
for(i in a) { 
    s.push(i);  
} 
s.reverse(); 
for(i in s) { 
    trace(i);  
} 

मैं ग्रहण करेंगे वहाँ एक आसान तरीका हो गया है कि, या ऐसा करने का कम से कम तेजी से। हम आकार को नहीं जान सकते क्योंकि इटरेटर कक्षा में कोई नहीं है, इसलिए हम तीर सरणी पर पुश को घुमा नहीं सकते हैं। लेकिन हम रिवर्स को हटा सकते हैं क्योंकि हम temp सरणी के आकार को जानते हैं।

var a = [1,2,3,4].iterator(); 
// Actual reverse iteration bellow 
var s = []; 
for(i in a) { 
    s.push(i);
} var total = s.length; var totalMinusOne = total - 1; for(i in 0...total) { trace(s[totalMinusOne - i]);
}

Is there any more optimisations that could be used to remove the possibility of the array?

+0

इस के आलसी कार्यान्वयन को रखने के लिए यह अच्छा होगा, क्योंकि इटेटर अपने आप में आलसी हैं (अगली विधि को कॉल करने के लिए यह आपके ऊपर है) – simonrichardson

उत्तर

3

It bugs me that you have to duplicate the list, though... that's nasty. I mean, the data structure would ALREADY be an array, if that was the right data format for it. A better thing (less memory fragmentation and reallocation) than an Array (the "[]") to copy it into might be a linked List or a Hash.

But if we're using arrays, then Array Comprehensions (http://haxe.org/manual/comprehension) are what we should be using, at least in Haxe 3 or better:

var s = array(for (i in a) i); 

Ideally, at least for large iterators that are accessed multiple times, s should be cached.

To read the data back out, you could instead do something a little less wordy, but quite nasty, like:

for (i in 1-s.length ... 1) { 
    trace(s[-i]); 
} 

But that's not very readable and if you're after speed, then creating a whole new iterator just to loop over an array is clunky anyhow. Instead I'd prefer the slightly longer, but cleaner, probably-faster, and probably-less-memory:

var i = s.length; 
while (--i >= 0) { 
    trace(s[i]); 
} 
2

First of all I agree with Dewi Morgan duplicating the output generated by an iterator to reverse it, somewhat defeats its purpose (or at least some of its benefits). Sometimes it's okay though.

Now, about a technical answer:

By definition a basic iterator in Haxe can only compute the next iteration.

On the why iterators are one-sided by default, here's what we can notice:

  1. if all if iterators could run backwards and forwards, the Iterator classes would take more time to write.
  2. not all iterators run on collections or series of numbers.

E.g. 1: an iterator running on the standard input.

E.g. 2: an iterator running on a parabolic or more complicated trajectory for a ball.

E.g. 3: slightly different but think about the performance problems running an iterator on a very large single-linked list (eg the class List)। कुछ पुनरावृत्तियों को पुनरावृत्ति के बीच में बाधित किया जा सकता है (Lambda.has() और Lambda.indexOf() उदाहरण के लिए जैसे ही एक मैच होता है, इसलिए आप सामान्य रूप से इस बारे में नहीं सोचना चाहते कि संग्रह के रूप में क्या किया जाता है लेकिन एक इंटरप्टिबल श्रृंखला के रूप में और चरण द्वारा पुनरावृत्त चरण की प्रक्रिया)।

हालांकि इसका मतलब यह नहीं है कि आपको दो तरीकों के इटरेटर को परिभाषित नहीं करना चाहिए यदि आपको उनकी आवश्यकता है (मैंने इसे हक्स में कभी नहीं किया है लेकिन यह असंभव प्रतीत नहीं होता है), पूर्ण रूप से दो तरीकों से इटरेटर्स प्राकृतिक नहीं हैं, और इटरेटर को ऐसा करने के लिए मजबूर करना है जो कोडिंग को जटिल बना देगा।

एक मध्यवर्ती और अधिक लचीला समाधान बस (एक कस्टम ArrayExt वर्ग का उपयोग कर के साथ) ReverseXxIter जहां जरूरत है, उदाहरण के ReverseIntIter के लिए, या Array.reverseIter() है। इसलिए प्रत्येक प्रोग्रामर के लिए अपने उत्तर लिखने के लिए यह छोड़ा गया है, मुझे लगता है कि यह एक अच्छा संतुलन है; जबकि शुरुआत में अधिक समय और निराशा होती है (सभी को शायद एक ही तरह का प्रश्न होता है), आप भाषा को बेहतर तरीके से जानना समाप्त कर देते हैं और अंत में आपके लिए केवल फायदे हैं।