PHP-如何计算一个数字

PHP-如何计算一个数字,php,generator,yield,Php,Generator,Yield,使用PHP>=5.5如果我们有一个生成值的方法,那么计算这些值的最佳方法是什么 我所期望的是能够将生成器转换为数组并进行计数,但它将返回一个空数组。Count()也不工作,因为生成器报告为空,尽管它不是空的 我对此感到困惑。如果你不需要计算一个发电机的产量,那么这是一个很好的功能,否则我看不出它有什么意义。有一种方法可以检测生成器是否为空,这是通过使用key()方法实现的,如果它返回NULL,那么要么没有收益,要么生成器已经被迭代,这意味着当前指针为NULL 您应该理解,这不是数据结构——它是类

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

我所期望的是能够将生成器转换为数组并进行计数,但它将返回一个空数组。Count()也不工作,因为生成器报告为空,尽管它不是空的


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

您应该理解,这不是数据结构——它是类的一个实例,实际上,它是一种特殊的
迭代器。因此,您无法直接计算它的项(准确地说,这是因为
Generator
类只实现接口,而不实现接口。老实说,我无法想象它如何实现这一点)

要使用本机生成器计算值,必须对其进行迭代。但这不是常识所能做到的——因为在大多数情况下,由你决定将产生多少项目。著名的
xrange()
手册样本:

function xrange($start, $limit, $step = 1) {
    if ($start < $limit) {
        if ($step <= 0) {
            throw new LogicException('Step must be +ve');
        }

        for ($i = $start; $i <= $limit; $i += $step) {
            yield $i;
        }
    } else {
        if ($step >= 0) {
            throw new LogicException('Step must be -ve');
        }

        for ($i = $start; $i >= $limit; $i += $step) {
            yield $i;
        }
    }
}
-使用方法:

var_dump(getCount(xrange(1, 100, 10)));//10
var_dump(getCount(xrange(1, 100, 1)));//100

-正如你所看到的,“计数”将会改变。更糟糕的是,生成器并不一定是有限的。它可能会产生无穷多的值集(例如,边界是在外部循环中定义的),这也是使“计数”几乎毫无意义的另一个原因。

如果必须这样做,请遵循本机函数的线性关系:

count(iterator_to_array($generator, false));
但是,请注意:在此之后,
$generator
将被执行和使用。因此,如果您将相同的
$generator
放入下一行中的
foreach
,它将循环0次


生成器在设计上是高度动态的(与数组等固定数据结构相比),这就是为什么它们不提供
->count()
->rewind()

,而您不能使用
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;
}
函数生成(&$count=0){
//我们有四件事
$count=4;
对于($i=0;$i<$count;$i++){
收益率1美元;
}
}
$foo=生成($count);
echo$count;//4.
foreach($foo作为$i){
echo$i;
}

这样做的缺点是,它不会告诉你还有多少剩余,而是告诉你它是从多少开始的。

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

案例1:我在迭代之前无法计数,而且我关心值

// The plain old solution
$count = 0;
foreach($traversable as $value) {
    // Do something with $value, then…
    ++$count;
}
// let's iterator_count() do it for me
$count = iterator_count($traversable);
案例2:我在迭代之前无法计数,但我不关心值

// The plain old solution
$count = 0;
foreach($traversable as $value) {
    // Do something with $value, then…
    ++$count;
}
// let's iterator_count() do it for me
$count = iterator_count($traversable);
案例3:我可以在迭代之前计数,但我不关心值

// The plain old solution
$count = 0;
foreach($traversable as $value) {
    // Do something with $value, then…
    ++$count;
}
// let's iterator_count() do it for me
$count = iterator_count($traversable);
我尽量不使用发电机

例如(使用SQL后端):

SELECT * FROM mytable; // then counting results
其他示例(来自Alma Do的xrange):

案例4:我可以在迭代之前计数,而且我关心值

// The plain old solution
$count = 0;
foreach($traversable as $value) {
    // Do something with $value, then…
    ++$count;
}
// let's iterator_count() do it for me
$count = iterator_count($traversable);
我可以使用生成器和计数函数

$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
}
资料来源:


我明白。在我的情况下,我实际上是从数据库中产生一个行循环中的对象,这意味着虽然有一个“yield”语句,但它会被重复多次。我能想到的唯一方法是克隆生成器并对其进行迭代(允许原始生成器仍然对其数据进行迭代)或分别计算行数。所以根据你说的,我一定不是在最佳实践中使用它?在SQL中有
COUNT
grouping函数。如果生成器是无限的,那么计数就没有用了,但是如果一个人无限地使用同一个生成器,那么在哪一点上它会停止允许你使用生成器中存储的值呢?它最终将不得不停止,否则它只会毫无意义地产生价值,对吗?通过计算行数,我的意思是使用COUNT,但它必须是一个单独的查询。一个用于获取行数,另一个用于获取数据。然后生成计数和数据,这意味着生成器中的第一个值将是行计数。你会这样做吗?问题是-你必须迭代才能得到计数。这听起来不是个好主意,尤其是当结果集中有很多元素时。对于太小的功能,开销太大。我仍然建议使用SQL的
COUNT()
,因为它就是要这样做的。你可以一直使用
迭代器对数组进行迭代器
,但是它失去了兴趣,因为你必须对所有的值进行迭代器才能找到它。在发布这篇文章的时候,我只尝试了COUNT(),这在文章中提到过,但没有起作用。我也在讨论这个话题,因为这是我遇到的一个特定的编程问题。至于提供一个代码示例,我想我可以展示我当前的使用情况,但我希望那些点击这篇文章的人无论如何都会知道在PHP中使用收益率。说到这里,我不知道我违反了任何规则,但如果我违反了规则,我真的很抱歉。希望使用本机函数可以使此方法比@Alma Do描述的方法更有效。是否可以使用它对数组进行排序而不是计数?