【问题标题】:Why does 'yield' not overwrite key value pairs in PHP?为什么'yield'不会覆盖 PHP 中的键值对?
【发布时间】:2016-01-23 02:05:36
【问题描述】:

我在使用生成器时遇到了这种奇怪的行为,PHP 手册中没有描述。

我有两个 foreach 循环 - 第一个设置一些默认值,第二个覆盖它们。但是由于缺少一些键:值对,我无法使用 array_merge(),因此我尝试使用生成器来实现此目的。

我发现即使docs say:

关联数组中的 yield 键也会被覆盖

产生键/值对的语法与用于定义关联数组的语法非常相似,如下所示。

例子:

function yieldTest()
{
    // those are array values (in my code - taken from data source; here static example)
    $arr1 = ['a' => 1, 'b' => 2, 'c' => 3];
    $arr2 = ['b' => 'B', 'd' => 'D'];

    // 1st loop
    foreach ($arr1 as $k => $v) {
        yield $k => $v;
    }

    // 2nd loop
    foreach ($arr2 as $k => $v) {
        yield $k=>$v;
    }
}

foreach(yieldTest() as $k=>$v) {
    var_dump($k . ' = ' . $v) . "\n";
}

结果是

string(5) "a = 1"
string(5) "b = 2"
string(5) "c = 3"
string(5) "b = B"
string(5) "d = D"

所以密钥并没有被过度篡改。我期待得到以下输出:

string(5) "a = 1"
string(5) "b = B"
string(5) "c = 3"
string(5) "d = D"

这是正确的行为吗?

【问题讨论】:

  • 您看到了我希望看到的行为。我不明白您认为使用 array_merge 有什么问题?
  • print_r(yieldTest()) 的输出是什么; ?
  • 哪一点是奇怪的行为?生成器产生你告诉它产生的东西,无论你之前是否产生过相同的键,键是布尔值、整数还是对象(如果你真的想的话,你甚至可以产生一个资源作为键)

标签: php generator yield


【解决方案1】:

生成器不是关联数组。它说“[t]生成键/值对的语法与[..]关联数组非常相似”;它根本没有说生成器 表现 像关联数组。

事实上,它不能表现相同并删除重复的键,因为这些键不是一次性知道的。每个密钥都是在需要时生成的,而不是之前生成的。用于循环生成器的foreach 语法实际上是语法糖:

function foo() {
    while (true) {
        yield mt_rand(1, 2) => 'foo';
    }
}

$foo = foo();
$foo->next();
echo $foo->key(), ' => ', $foo->current(), PHP_EOL;
$foo->next();
echo $foo->key(), ' => ', $foo->current(), PHP_EOL;
$foo->next();
echo $foo->key(), ' => ', $foo->current(), PHP_EOL;
$foo->next();
echo $foo->key(), ' => ', $foo->current(), PHP_EOL;

This will yield the same key many times, unpredictably. 很明显,它的行为根本不像一个数组。它只产生一对值,但它们根本不是数组的一部分,因此不会重复数据删除。此外,生成器仅在被要求时才产生下一个值,否则上述将导致无限循环。

【讨论】:

  • 谢谢。这是非常有用的解释。
猜你喜欢
  • 1970-01-01
  • 2021-02-07
  • 1970-01-01
  • 1970-01-01
  • 2019-06-08
  • 2019-05-03
  • 1970-01-01
  • 2020-12-31
  • 1970-01-01
相关资源
最近更新 更多