假設我有以下遞回函式將陣列轉換為生成器:
function traverse(array $items): Generator {
if (!empty($items)) {
yield $items[0];
array_shift($items);
yield from traverse($items);
}
}
運行這個函式并通過 a 迭代生成器foreach給出了預期的結果:
$values = traverse(['a', 'b', 'c', 'd', 'e']);
foreach ($values as $value) {
echo $value;
}
// 'abcde' is echoed
但是,當我使用內置函式時iterator_to_array(),得到以下結果:
$values = iterator_to_array(traverse(['a', 'b', 'c', 'd', 'e']));
foreach ($values as $value) {
echo $value;
}
// Only 'e' is echoed
我希望兩段代碼的行為相同,但他們沒有。為什么他們的行為不同?
我在 PHP 8.1 上運行它。
uj5u.com熱心網友回復:
從手冊:
yield from 不會重置密鑰。它保留由 Traversable 物件或陣列回傳的鍵。因此,某些值可能與另一個 yield 或 yield from 共享一個公共鍵,這在插入陣列時會用該鍵覆寫以前的值。
這很重要的一個常見情況是 iterator_to_array() 默認回傳一個鍵控陣列,這可能會導致意外的結果。iterator_to_array() 有第二個引數 use_keys,它可以設定為 false 以收集所有值,同時忽略生成器回傳的鍵。
您的生成器每次都回傳一個具有相同鍵的專案(因為它們在array_shift呼叫后被重置),因此iterator_to_array用以下專案覆寫每個專案。這就是為什么您只看到回傳的最后一個元素。
如果您將use_keys引數作為false傳遞給函式,您將獲得所需的行為,例如
$values = iterator_to_array(traverse(['a', 'b', 'c', 'd', 'e']), false);
見https://3v4l.org/jWbt4
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/398926.html
