PHP - 如何计算生成器的产量

问题描述 投票:6回答:4

使用PHP> = 5.5如果我们有一个产生值的方法,那么计算这些值的最佳方法是什么?

我期待的是能够将Generator转换为数组并计算它,但它会返回一个空数组。 Count()也不起作用,因为尽管不是空的,但报告为空。

我对此感到困惑。如果你不需要计算发电机的产量,那么这是一个很好的功能,否则我没有看到它的重点。有一种方法可以检测生成器是否为空,这是通过使用key()方法,如果它返回NULL,则无法产生或者已经迭代了生成器,这意味着当前指针为空。

php generator yield
4个回答
1
投票

实际上,这取决于你是哪种情况:

案例1:在迭代之前我无法计算,我关心价值观

// The plain old solution
$count = 0;
foreach($traversable as $value) {
    // Do something with $value, then…
    ++$count;
}

案例2:我在迭代之前无法计算,但我不关心价值观

// let's iterator_count() do it for me
$count = iterator_count($traversable);

案例3:我可以在迭代之前计算,但我不关心价值观

我尽量不使用发电机。

例如(使用SQL后端):

SELECT count(1) FROM mytable; // then return result

比...更好

SELECT * FROM mytable; // then counting results

其他例子(来自Alma Do的xrange):

// More efficient than counting by iterating
function count_xrange($start, $limit, $step = 1) {
    if (0 === $step) throw new LogicException("Step can't be 0");
    return (int)(abs($limit-$start) / $step) + 1;
}

案例4:我可以在迭代之前计算,我关心价值观

我可以使用生成器和计数功能

$args = [0,17,2];

$count = count_xrange(...$args);
$traversable = xrange(...$args);

案例5:案例4,我希望所有人都在一个对象中

我可以“装饰”迭代器来制作一个可数的迭代器

function buildCountableIterator(...$args) {

    $count = count_xrange(...$args);
    $traversable = xrange(...$args);

    return new class($count, $traversable) extends \IteratorIterator implements \Countable {
        private $count;
        public function __construct($count, $traversable) {
            parent::__construct($traversable);
            $this->count = $count;
        }
        public function count() {
            return $this->count;
        }
    }
}

$countableIterator = buildCountableIterator(1, 24, 3);

// I can do this because $countableIterator is countable
$count = count($countableIterator); 

// And I can do that because $countableIterator is also an Iterator
foreach($countableIterator as $item) {
    // do something
}

资料来源:


0
投票

虽然您不能使用count(),但您可以使用引用来设置计数,以使外部世界可以访问它。

function generate(&$count = 0) {
    // we have 4 things
    $count = 4;
    for($i = 0; $i < $count; $i++) {
        yield $i;
    }
}

$foo = generate($count);
echo $count; // 4
foreach ($foo as $i) {
     echo $i;
}

在这方面的缺点是它不会告诉你有多少剩余,但它开始有多少。

© www.soinside.com 2019 - 2024. All rights reserved.