From 8d37a362f0def3c6cd94f31adab8f2d47a75a28e Mon Sep 17 00:00:00 2001 From: Florent Bruneau Date: Tue, 16 Feb 2010 22:11:58 +0100 Subject: [PATCH] Add map and filter functions on iterator. PlIterator PlIteratorUtils::map(PlIterator $src, $callback); PlIterator PlIteratorUtils::filter(PlIterator $src, $callback) Signed-off-by: Florent Bruneau --- classes/pliteratorutils.php | 127 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/classes/pliteratorutils.php b/classes/pliteratorutils.php index d70b050..ae3b491 100644 --- a/classes/pliteratorutils.php +++ b/classes/pliteratorutils.php @@ -59,6 +59,31 @@ class PlIteratorUtils { return new PlMergeIterator($iterators, $callback, $sorted); } + + + /** Build an iterator that contains only the elements of the given iterator that + * match the given condition. The condition should be a callback that takes an element + * and returns a boolean. + * @param iterator The source iterator + * @param callback The condition + * @return an iterator + */ + public static function filter(PlIterator $iterator, $callback) + { + return new PlFilterIterator($iterator, $callback); + } + + + /** Build an iterator that transforms the element of another iterator. The callback + * takes an element and transform it into another one. Be careful: if the result + * of the callback is null, the iteration ends. + * @param iterator The source iterator + * @param callback The transformer. + */ + public static function map(PlIterator $iterator, $callback) + { + return new PlMapIterator($iterator, $callback); + } } @@ -259,5 +284,107 @@ class PlMergeIterator implements PlIterator } } + +class PlFilterIterator implements PlIterator { + private $source; + private $callback; + private $element; + private $start; + + public function __construct(PlIterator $source, $callback) + { + $this->source = $source; + $this->callback = $callback; + $this->start = true; + $this->element = null; + } + + private function fetchNext() + { + do { + $current = $this->source->next(); + if (!$current) { + $this->element = null; + $this->start = false; + return; + } + $res = call_user_func($this->callback, $current); + if ($res) { + $this->element = $current; + return; + } + } while (true); + } + + public function next() + { + if ($this->element && $this->start) { + $this->start = false; + } + $elt = $this->element; + if ($elt) { + $this->fetchNext(); + } + return $elt; + } + + public function total() + { + /* This is an approximation since the correct total + * cannot be computed without fetching all the elements + */ + return $this->source->total(); + } + + public function first() + { + return $this->start; + } + + public function last() + { + return !$this->start && !$this->element; + } +} + + +class PlMapIterator implements PlIterator +{ + private $source; + private $callback; + + public function __construct(PlIterator $source, $callback) + { + $this->source = $source; + $this->callback = $callback; + } + + public function next() + { + $elt = $this->source->next(); + if ($elt) { + return call_user_func($this->callback, $elt); + } else { + return null; + } + } + + public function total() + { + return $this->source->total(); + } + + public function first() + { + return $this->source->first(); + } + + public function last() + { + return $this->source->last(); + } +} + + // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: ?> -- 2.1.4