2012-11-29 30 views
9

IteratorAggregate एक बाहरी इटरेटर बनाने के लिए एक इंटरफेस है:PHP इंटरफेस IteratorAggregate बनाम इटरेटर?

class myData implements IteratorAggregate 
{ 
    public $property1 = "Public property one"; 
    public $property2 = "Public property two"; 
    public $property3 = "Public property three"; 

    public function __construct() 
    { 
     $this->property4 = "last property"; 
    } 

    public function getIterator() 
    { 
     return new ArrayIterator($this); 
    } 
} 

$obj = new myData; 

और तुम वस्तु foreach का उपयोग कर पार करने के लिए सक्षम हो जाएगा: Iterator एक इंटरफेस है जबकि

foreach($obj as $key => $value) { 
    var_dump($key, $value); 
    echo "\n"; 
} 

बाहरी इटरेटर्स या ऑब्जेक्ट्स के लिए जिन्हें आंतरिक रूप से:

को पुन: सक्रिय किया जा सकता है

$it = new myIterator; 

foreach($it as $key => $value) { 
    var_dump($key, $value); 
    echo "\n"; 
} 

तो किसी को समझा सकता है इसलिए हम दो इंटरफेस की जरूरत है और क्या उन दोनों के बीच अंतर नहीं है:

class myIterator implements Iterator 
{ 
    private $position = 0; 
    private $array = array('one', 'two', 'three'); 

    function rewind() 
    { 
     $this->position = 0; 
    } 

    function current() 
    { 
     return $this->array[$this->position]; 
    } 

    function key() 
    { 
     return $this->position; 
    } 

    function next() 
    { 
     ++$this->position; 
    } 

    function valid() 
    { 
     return isset($this->array[$this->position]); 
    } 
} 

और फिर, आप यह मूल रूप से एक ही तरह से पार कर सकते हैं?

उत्तर

12

मुझे लगता है कि IteratorAggregate उन मामलों के लिए है जहां आप समय बचाने के लिए चाहते हैं, और Iterator उन मामलों के लिए है जहां आपको अपनी ऑब्जेक्ट के माध्यम से पुनरावृत्ति पर अच्छे नियंत्रण की आवश्यकता है। उदाहरण के लिए यह आपको next(), key() या prev() असफलताओं, कैशिंग (यदि आप किसी नेटवर्क के माध्यम से डेटा लेते हैं) के माध्यम से कस्टम अपवाद जोड़ सकते हैं, तो उन्हें वापस करने से पहले प्रीप्रोसेस मान।

+0

मुझे लगता है कि आप कस्टम तरीकों के बारे में गलत हैं। – tacone

+0

और यदि आप और भी समय बचा सकते हैं, तो आप 'getIterator' से मूल्यों को' उपज 'कर सकते हैं। – Bell

6

IteratorAggregate एक इटरेटर को लागू करने का एक आसान तरीका है। नुकसान यह है कि आप next(), key(), आदि विधियों को जोड़ सकते हैं, क्योंकि उन्हें सामान्य foreach ट्रैवर्सल के दौरान कॉल नहीं किया जाएगा।

यदि आपको कस्टम तरीकों को लागू करने की आवश्यकता है, तो आपको IteratorIterator का विस्तार करने के लिए OuterIterator या (आसान) लागू करने की आवश्यकता है।

IteratorAggregate के साथ लाभ गति है, यह इसके विकल्पों की तुलना में अधिक तेज़ है। इसके साथ समस्या यह है कि ... नाम के बावजूद यह एक पुनरावर्तक नहीं है लेकिन एक ट्रैवर्सबल (फिर से, कोई अगली, कुंजी, वर्तमान, मान्य, रिवाइंड विधियों)। (यह भी ध्यान रखें echo सकल के next विधि के अंदर:

यहाँ एक सरल बेंचमार्क मैं IteratorAggregate, IteratorIterator और OuterIterator में से हर एक दोनों का उपयोग कर iterator_to_array और foreach के लिए पुनरावृत्तियों की 1 लाख के साथ मेरे गरीब लैपटॉप पर चलने कोई 'एक्स' मुद्रित हो जाता है, सबूत यह लागू नहीं किया जाता)

$ repeat 3 php benchIterator.php 
------------------------------------ 
Outer_ToArray: 569.61703300476 ms 
Aggregate_ToArray: 552.38103866577 ms 
IteratorIt_ToArray: 546.95200920105 ms 
Outer_Foreach: 1679.8989772797 ms 
IteratorIt_Foreach: 1019.6850299835 ms 
Aggregate_Foreach: 367.35391616821 ms 
------------------------------------ 
Outer_ToArray: 570.75309753418 ms 
Aggregate_ToArray: 544.40784454346 ms 
IteratorIt_ToArray: 555.06300926208 ms 
Outer_Foreach: 1682.2130680084 ms 
IteratorIt_Foreach: 988.21592330933 ms 
Aggregate_Foreach: 356.41598701477 ms 
------------------------------------ 
Outer_ToArray: 566.06101989746 ms 
Aggregate_ToArray: 543.1981086731 ms 
IteratorIt_ToArray: 546.28610610962 ms 
Outer_Foreach: 1663.2289886475 ms 
IteratorIt_Foreach: 995.28503417969 ms 
Aggregate_Foreach: 356.16087913513 ms 

यहाँ कोड मैं बेंचमार्क के लिए इस्तेमाल किया है:

<?php 

class Aggregate implements \IteratorAggregate 
{ 
    protected $var; 

    public function __construct($var = null) 
    { 
     if (is_array($var)) { 
      $this->var = new ArrayIterator($var); 
     } 
     if ($var instanceof \Traversable) { 
      $this->var = $var; 
     } 
    } 
    public function next() 
    { 
     echo 'x'; 
    } 
    public function toArray() 
    { 
     return iterator_to_array($this->var, true); 
    } 

    public function getIterator() 
    { 
     return $this->var; 
    } 

} 

class Outer implements \OuterIterator 
{ 
    protected $var; 

    public function __construct($var = null) 
    { 
     if (is_array($var)) { 
      $this->var = new ArrayIterator($var); 
     } 
     if ($var instanceof \Traversable) { 
      $this->var = $var; 
     } 
    } 

    public function toArray() 
    { 
     return iterator_to_array($this->var, true); 
    } 

    public function getInnerIterator() 
    { 
     return $this->var; 
    } 

    public function current() 
    { 
     return $this->var->current(); 
    } 
    public function next() 
    { 
     $this->var->next(); 
    } 
    public function key() 
    { 
     return $this->var->key(); 
    } 
    public function valid() 
    { 
     return $this->var->valid(); 

    } 
    public function rewind() 
    { 
    $this->var->rewind(); 

    } 
} 


class IteratorIt extends IteratorIterator 
{ 
    public function __construct($var = null) 
    { 
     if (is_array($var)) { 
      $var = new ArrayIterator($var); 

     } 
     parent::__construct($var); 

    } 

    public function toArray() 
    { 
     return iterator_to_array($this->getInnerIterator(), true); 
    } 
    public function getIterator() 
    { 
     return $this->getInnerIterator(); 
    } 
} 

function bench($name, $test) 
{ 
    echo "$name: "; 
    $start = microtime(true); 
    $test(); 
    $time = microtime(true); 
    $time -= $start; 

    echo ($time * 1000) . ' ms' . PHP_EOL; 
} 

$max = 1e6; 
$array = range (1, 1e6); 
$testSuites = [ 
    'Outer_ToArray' => function() use ($max, $array) { 
     $iterator = new Outer($array); 
     $r = $iterator->toArray(); 
    }, 
    'Aggregate_ToArray' => function() use ($max, $array) { 
     $iterator = new Aggregate($array); 
     $r = $iterator->toArray(); 
    }, 
    'IteratorIt_ToArray' => function() use ($max, $array) { 
     $iterator = new IteratorIt($array); 
     $r = $iterator->toArray(); 
    }, 
    'Outer_Foreach' => function() use ($max, $array) { 
     $iterator = new Outer($array); 
     foreach ($iterator as $k => $v) 
     { 

     } 
    }, 
    'IteratorIt_Foreach' => function() use ($max, $array) { 
     $iterator = new IteratorIt($array); 
     foreach ($iterator as $k => $v) 
     { 

     } 
    }, 
    'Aggregate_Foreach' => function() use ($max, $array) { 
     $iterator = new Aggregate($array); 
     foreach ($iterator as $k => $v) 
     { 

     } 
    }, 
]; 

echo '------------------------------------'.PHP_EOL; 
foreach ($testSuites as $name => $test) { 
    bench($name, $test); 
} 
3

उनके बीच क्या अंतर है?

नामों में अंतर ("कुल")।

कुल अर्थ क्या है?

कुल राज्य बाहरी वस्तुओं को अपने सदस्यों के संदर्भ रखने से मना कर कुल मिलाकर किए गए परिवर्तनों की स्थिरता की गारंटी देता है। (wikipedia)


टीसी कोड:

$renderFunction = function($iterator) { 
    foreach($iterator as $key => $value) { 
     echo "$key: $value\n"; 
     foreach($iterator as $key => $value) { 
      echo " $key: $value\n"; 
     } 
    } 
}; 

$renderFunction(new myData); // Aggregate on 
$renderFunction(new myIterator); // Aggregate off 

आप मामलों में क्या उम्मीद करते हैं:

class myData implements IteratorAggregate {//your implementation} 

class myIterator implements Iterator {//your implementation} 

यहाँ सकल की स्पष्टता के लिए कोड है?

https://3v4l.org/JHDNQ

property1: Public property one 
    property1: Public property one 
    property2: Public property two 
    property3: Public property three 
    property4: last property 
property2: Public property two 
    property1: Public property one 
    property2: Public property two 
    property3: Public property three 
    property4: last property 
property3: Public property three 
    property1: Public property one 
    property2: Public property two 
    property3: Public property three 
    property4: last property 
property4: last property 
    property1: Public property one 
    property2: Public property two 
    property3: Public property three 
    property4: last property 

0: one 
    0: one 
    1: two 
    2: three 
+0

मैं आपके द्वारा प्रदान किए गए लिंक में उत्सुक हूं, ऐसा लगता है कि php7 उदाहरण के लिए php 5.6 से धीमा है। क्या यह सामान्य है? या मैं सभी – Dazag

+0

@Dazag पर डेटा को समझ नहीं पा रहा हूं, आप सही हैं, लेकिन समय के साथ यह थोड़ा अलग है और मुझे नहीं पता कि वहां opcache का उपयोग किया गया है .... –

2

बनाम IteratorAggregate लागू करने से, हम (अन्य वर्ग के लिए इटरेटर कार्य (key(), next(), current(), valid(), rewind()) को लागू करने का काम सौंपने केवल लागू करने से getIterator()

इस तरह, यह हमें ओओपी में अलग-अलग चिंताओं को प्राप्त करने में मदद करता है।

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

  • कोई संबंधित समस्या नहीं^_^