使用PHP> = 5.5如果我们有一个产生值的方法,那么计算这些值的最佳方法是什么?
我期待的是能够将Generator转换为数组并计算它,但它会返回一个空数组。 Count()也不起作用,因为尽管不是空的,但报告为空。
我对此感到困惑。如果你不需要计算发电机的产量,那么这是一个很好的功能,否则我没有看到它的重点。有一种方法可以检测生成器是否为空,这是通过使用key()方法,如果它返回NULL,则无法产生或者已经迭代了生成器,这意味着当前指针为空。
实际上,这取决于你是哪种情况:
案例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
}
资料来源:
虽然您不能使用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;
}
在这方面的缺点是它不会告诉你有多少剩余,但它开始有多少。