2011-07-03 27 views
15

क्या array_map करने का एक तरीका है लेकिन एक पुनरावर्तक के रूप में?PHP आलसी सरणी मानचित्रण

उदाहरण के लिए:

foreach (new MapIterator($array, $function) as $value) 
{ 
    if ($value == $required) 
     break; 
} 

यह करने के लिए कारण यह है कि $ समारोह है गणना करने के लिए कठिन है और $ सरणी भी कई तत्व है, केवल जब तक मैं एक विशिष्ट मूल्य को खोजने के लिए नक्शे की जरूरत है। array_map सभी मूल्यों की गणना करेगा इससे पहले कि मैं अपनी इच्छानुसार खोज कर सकूं।

मैं खुद इटरेटर को कार्यान्वित कर सकता हूं, लेकिन मैं जानना चाहता हूं कि ऐसा करने का मूल तरीका है या नहीं। मैं PHP दस्तावेज खोज कुछ भी नहीं मिला।

उत्तर

6

संक्षेप में: नहीं

कोई आलसी इटरेटर पीएचपी में बनाया मानचित्रण है। एक गैर-आलसी फ़ंक्शन iterator_apply() है, लेकिन कुछ भी नहीं है जो आप के बाद हैं।

जैसा कि आपने कहा था, आप खुद को लिख सकते हैं। मेरा सुझाव है कि आप IteratorIterator का विस्तार करें और वर्तमान() विधि को ओवरराइड करें।

यदि ऐसी कोई बात थी तो इसे या तो here या here दस्तावेज किया जाएगा।

+0

यह वास्तव में '' IteratorIterator' Iterator' इंटरफेस को लागू करने में एक पूरा डेकोरेटर लेखन के बजाय का उपयोग करने के लिए एक अच्छा विचार है। – Harmen

1

मैं एक साधारण मानचित्र वर्ग कार्यान्वयन के बारे में सोच रहा हूं जो कुंजी की एक सरणी और मूल्यों की एक सरणी का उपयोग करता है।

while ($map->hasNext()) { 
    $value = $map->next(); 
    ... 
} 
0
foreach ($array as $key => $value) { 
    if ($value === $required) { 
     break; 
    } else { 
     $array[$key] = call_back_function($value); 
    } 
} 

प्रक्रिया और जब तक आवश्यक मूल्य पाया जाता है पुनरावृति: समग्र कार्यान्वयन जावा के इटरेटर वर्ग की तरह के माध्यम से इसे पसंद किया जा सकता है, जबकि आप पुनरावृति होगी।

0

पुनरावर्तक के साथ परेशान न हों, जवाब है:

foreach ($array as $origValue) 
{ 
    $value = $function($origValue); 
    if ($value == $required) 
     break; 
} 
+0

आआंद इसे कम कर दिया गया था क्योंकि? ओपी ने जो कुछ भी पूछा, उसे साइड इफेक्ट्स के बिना, किसी और ने _how_ का उदाहरण प्रदान नहीं किया। – Izkata

+0

मैंने इसे कम नहीं किया, लेकिन यह एक आलसी समाधान नहीं है, केवल एक छोटा सर्किटिंग समाधान है। इसमें केवल उदाहरण शामिल हैं, ओपी की संभावनाओं की पूरी श्रृंखला नहीं है। (हालांकि स्वीकार्य उत्तर कोई कोड प्रदान नहीं करता है, यह सही दिशा में इंगित करता है।) – Brilliand

0

मैं उस उद्देश्य के लिए एक कॉलबैक उपयोग करने के लिए इस वर्ग के लिए लिखा था। उपयोग:

$array = new ArrayIterator(array(1,2,3,4,5)); 
$doubles = new ModifyIterator($array, function($x) { return $x * 2; }); 

परिभाषा (अपनी जरूरत के लिए संशोधित करने के लिए स्वतंत्र लग रहा है):

class ModifyIterator implements Iterator { 
    /** 
    * @var Iterator 
    */ 
    protected $iterator; 

    /** 
    * @var callable Modifies the current item in iterator 
    */ 
    protected $callable; 

    /** 
    * @param $iterator Iterator|array 
    * @param $callable callable This can have two parameters 
    * @throws Exception 
    */ 
    public function __construct($iterator, $callable) { 
     if (is_array($iterator)) { 
      $this->iterator = new ArrayIterator($iterator); 
     } 
     elseif (!($iterator instanceof Iterator)) 
     { 
      throw new Exception("iterator must be instance of Iterator"); 
     } 
     else 
     { 
      $this->iterator = $iterator; 
     } 

     if (!is_callable($callable)) { 
      throw new Exception("callable must be a closure"); 
     } 

     if ($callable instanceof Closure) { 
      // make sure there's one argument 
      $reflection = new ReflectionObject($callable); 
      if ($reflection->hasMethod('__invoke')) { 
       $method = $reflection->getMethod('__invoke'); 
       if ($method->getNumberOfParameters() !== 1) { 
        throw new Exception("callable must have only one parameter"); 
       } 
      } 
     } 

     $this->callable = $callable; 
    } 

    /** 
    * Alters the current item with $this->callable and returns a new item. 
    * Be careful with your types as we can't do static type checking here! 
    * @return mixed 
    */ 
    public function current() 
    { 
     $callable = $this->callable; 
     return $callable($this->iterator->current()); 
    } 

    public function next() 
    { 
     $this->iterator->next(); 
    } 

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

    public function valid() 
    { 
     return $this->iterator->valid(); 
    } 

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

PHP के iterators काफी उपयोग करने के लिए बोझिल कर रहे हैं, खासकर अगर गहरी घोंसले की आवश्यकता है। LINQ, जो सरणी और वस्तुओं के लिए एसक्यूएल जैसी क्वेरी लागू करता है, इसके लिए बेहतर अनुकूल है, क्योंकि यह आसान विधि श्रृंखला को अनुमति देता है और आलसी आलसी है। इसे लागू करने वाले पुस्तकालयों में से एक YaLinqo * है। 70 समग्र अधिक

// $array can be an array or \Traversible. If it's an iterator, it is traversed lazily. 
$is_value_in_array = from($array)->contains(2); 

// where is like array_filter, but lazy. It'll be called only until the value is found. 
$is_value_in_filtered_array = from($array)->where($slow_filter_function)->contains(2); 

// select is like array_map, but lazy. 
$is_value_in_mapped_array = from($array)->select($slow_map_function)->contains(2); 

// first function returns the first value which satisfies a condition. 
$first_matching_value = from($array)->first($slow_filter_function); 
// equivalent code 
$first_matching_value = from($array)->where($slow_filter_function)->first(); 

कई और अधिक कार्यों वहाँ रहे हैं,: इसके साथ, आप इस तरह मानचित्रण और छानने प्रदर्शन कर सकते हैं।

* मुझे

5

द्वारा विकसित यह एक आलसी संग्रह नक्शे समारोह है कि तुम वापस एक Iterator देता है:

/** 
* @param array|Iterator $collection 
* @param callable $function 
* @return Iterator 
*/ 
function collection_map($collection, callable $function) { 
    foreach($collection as $element) { 
     yield $function($element); 
    } 
} 
+0

'संग्रह' वर्ग सदस्य फ़ंक्शन के बजाए इसे एक निःशुल्क फ़ंक्शन बनाने का अच्छा विचार – Harmen

0

Non-standard PHP library पर एक नज़र डालें।यह एक lazy map कार्य है:

use function \nspl\a\lazy\map; 

$heavyComputation = function($value) { /* ... */ }; 
$iterator = map($heavyComputation, $list); 
संबंधित मुद्दे