2012-11-25 8 views
8

RecursiveIteratorIterator रिटर्न अतिरिक्त परिणाम देता है अगर rewind()while पाशRecursiveIteratorIterator अतिरिक्त तत्वों

उदाहरण

$array = array("A","B","C"); 
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($array)); 
//$iterator->rewind() ; this would fix it 
while ($iterator->valid()) { 
    print($iterator->current()) ; 
    $iterator->next(); 
} 

आउटपुट

AABC <--- Instead of ABC 
  • क्यों एक अतिरिक्त A नहीं C से पहले कहा जाता नहीं है?
  • सरणी rewind कॉल करने के लिए बिना कभी नहीं शुरू हो चुका है या कहा जाता है क्यों $iterator->rewind() जबकि पाश
  • foreach काम करता है पूरी तरह से करने के लिए आवश्यक है क्या foreach और while के बीच मतभेद जब iterators के साथ काम करने

Code In action

+1

IteratorIterator भी अजीब व्यवहार करता है अगर आप रिवाइंड नहीं कहते हैं। http://stackoverflow.com/questions/2458955/why-must-i-rewind-iteratoriterator – goat

+0

@rambocoder ने अभी भी यह देखा है .. यह एक बग की तरह दिख रहा है – Baba

+0

मैंने इसे अकेला छोड़ दिया क्योंकि मेरा पहला अंतर्ज्ञान अगर मैं था लेखन स्प्लिड, इसे [जैसे] [http://www.php.net/~helly/php/ext/spl/iteratoriterator_8inc_source.html) (बस विधि कॉल अग्रेषित करना होगा), शायद एक बूल चर के साथ वापसी मूल्यों को कैश करने के लिए। लेकिन, जब मैंने 'कैशिंगइटरेटर' जैसी चीजों के बारे में सोचना शुरू किया और पूरे इटरेटर/सजावटी प्रतिमान अभी भी 'रिकर्सिवइटरेटर इटरेटर' जैसे जटिल इटरेटर्स के साथ काम करेंगे, और पागल क्षणों में अपवाद/त्रुटियों को फेंक दिया जाएगा, बिना किसी बारे में सोचना बहुत जटिल था बहुत सारा प्रयास। – goat

उत्तर

5

मैं रिवर्स ऑर्डर में सवालों का जवाब देने जा रहा हूं:

foreachrewind कॉल करने के लिए बिना पूरी तरह से काम करता है क्या उन foreach और while के बीच मतभेद जब iterators

foreach आंतरिक rewind() के लिए एक कॉल करता है के साथ काम करने, यही कारण है कि आप इसे अपने आप को क्या करना है नहीं है। यह हमेशा किया जाता है, इसलिए यदि आप पहले से ही एक इटरेटर का उपयोग कर चुके हैं, तो foreach लूप शुरुआत से शुरू हो जाएगा। (आप इसे NoRewindIterator में लपेटकर इससे बच सकते हैं)।

सरणी कभी नहीं लगाते हैं या क्यों $ iterator-> रिवाइंड() पाश

एसपीएल iterators तैयार कर रहे हैं foreach साथ और प्रयोग की जाने वाली, जबकि डुप्लिकेट विधि में कॉल से बचने के लिए के लिए आवश्यक है बुलाया गया है ये मामला। यदि RecursiveIteratorIterator निर्माण पर RecursiveArrayIterator::rewind() विधि को कॉल करेगा, तो इसे फिर से कॉल किया जाएगा जब foreach लूप प्रारंभ होता है। यही कारण है कि कॉल नहीं किया जाता है।

अतिरिक्त ए नहीं सी क्यों?

इस पता लगाने के लिए यह देखने के लिए जो RecursiveArrayIterator के तरीकों वास्तव में कहा जाता हो अच्छा है:

<?php 

class DebugRAI extends RecursiveArrayIterator { 
    public function rewind() { echo __METHOD__, "\n"; return parent::rewind(); } 
    public function current() { echo __METHOD__, "\n"; return parent::current(); } 
    public function key() { echo __METHOD__, "\n"; return parent::key(); } 
    public function valid() { echo __METHOD__, "\n"; return parent::valid(); } 
    public function next() { echo __METHOD__, "\n"; return parent::next(); } 
} 

$array = array("A", "B", "C"); 
$iterator = new RecursiveIteratorIterator(new DebugRAI($array)); 
while ($iterator->valid()) { 
    echo $iterator->current(), "\n"; 
    $iterator->next(); 
} 

यह निम्न उत्पादन का उत्पादन:

DebugRAI::valid 
DebugRAI::current 
A 
DebugRAI::valid 
DebugRAI::valid 
A 
DebugRAI::next 
DebugRAI::valid 
DebugRAI::valid 
DebugRAI::current 
B 
DebugRAI::next 
DebugRAI::valid 
DebugRAI::valid 
DebugRAI::current 
C 
DebugRAI::next 
DebugRAI::valid 
DebugRAI::valid 

उत्पादन थोड़ा अजीब लग रहा है , विशेष रूप से दूसरा पुनरावृत्ति next() कॉल को याद करता है, इसलिए यह केवल उसी तत्व पर रहता है।

इस का कारण यह RecursiveIteratorIterator कार्यान्वयन में एक विशेष लक्षण है: Iterators RS_START राज्य में शुरू और इस राज्य में पहली next कॉल केवल hasChildren() की जाँच करता है, लेकिन वास्तव में अंतर्निहित इटरेटर के next() विधि कॉल नहीं करता है। ऐसा करने के बाद यह RS_NEXT मोड में स्विच करता है जिसमें next() कॉल ठीक से होता है। यही कारण है कि आगे की चाल एक कदम से देरी हो रही है।

मेरी आंखों में यह एक बग है, लेकिन https://bugs.php.net/bug.php?id=44063 अन्यथा दावा करता है।

+0

यह एक PHP बग की तरह दिखता है। यदि आपके पास यह जानने के लिए बहुत महत्वपूर्ण कारण है और यहां कोई भी जवाब देने में सक्षम नहीं है, तो आप ext/spl/spl_iterators.c –

+0

में भाग्य की कोशिश कर सकते हैं। यह कुछ अन्य इटरेटर्स के साथ भी है जो 'वैध()' को अनपेक्षित परिणाम देते हैं जब तक कि इटरेटर ठीक से नहीं है शुरूआत की गई है कि '__contruct()' के साथ-साथ 'रिवाइंड()' होने के साथ-साथ 'वैध()' कहा जा सकता है। यदि आप इसके आसपास काम नहीं कर सकते हैं, तो आप ['कैशिंगइटरेटर'] (http://php.net/CachingIterator) के साथ लपेट सकते हैं। – hakre

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