PHP Conference Japan 2024

SplDoublyLinkedList::shift

(PHP 5 >= 5.3.0, PHP 7, PHP 8)

SplDoublyLinkedList::shift從雙向鏈結串列的開頭移除一個節點

描述

public SplDoublyLinkedList::shift(): mixed

參數

此函式沒有參數。

回傳值

被移除的節點的值。

錯誤/例外

當資料結構為空時,丟擲 RuntimeException

新增筆記

使用者貢獻筆記 1 則筆記

fabs2s at marsatak dot org
7 年前
人們可能會預期 SplDoublyLinkedList::shift 會正確維護內部指標,但事實並非如此,即使您先倒回,也不會產生任何結果

<?php
while ($splDoublyLinkedList->valid()) {
yield
$splDoublyLinkedList->shift();
}
?>

這可能是設計使然,但以下內容會引發更多問題

<?php

$test
= new \SplDoublyLinkedList;
$dataSet = [
[
'id' => 1],
[
'id' => 2],
[
'id' => 3],
[
'id' => 4],
];

foreach (
$dataSet as $row) {
$test->push($row);
}

echo
"count: " . $test->count() . PHP_EOL;
echo
"valid: " . ($test->valid() ? 'true' : 'false') . PHP_EOL;
echo
"current: " . var_export($test->current(), true) . PHP_EOL;
echo
"key: " . $test->key() . PHP_EOL;
echo
"1st shift: " . var_export($test->shift(), true) . PHP_EOL;
echo
"count: " . $test->count() . PHP_EOL;
echo
"valid: " . ($test->valid() ? 'true' : 'false') . PHP_EOL;
echo
"current: " . var_export($test->current(), true) . PHP_EOL;
echo
"key: " . $test->key() . PHP_EOL;
echo
"2nd shift: " . var_export($test->shift(), true) . PHP_EOL;
echo
"count: " . $test->count() . PHP_EOL;
echo
"valid: " . ($test->valid() ? 'true' : 'false') . PHP_EOL;
echo
"current: " . var_export($test->current(), true) . PHP_EOL;
echo
"key: " . $test->key() . PHP_EOL;
echo
"rewinding... " . PHP_EOL;
$test->rewind();
echo
"current: " . var_export($test->current(), true) . PHP_EOL;
echo
"2nd shift: " . var_export($test->shift(), true) . PHP_EOL;
echo
"count: " . $test->count() . PHP_EOL;
echo
"valid: " . ($test->valid() ? 'true' : 'false') . PHP_EOL;
echo
"current: " . var_export($test->current(), true) . PHP_EOL;
echo
"key: " . $test->key() . PHP_EOL;
?>

將會產生
<?php

/*
count: 4
valid: false <== 首先要注意的是,除非先倒帶 (rewind),否則您沒有有效的指標
current: NULL <== 因此目前值為 NULL
key: 0 <== 但我們有一個有效的鍵
offsetGet(key): array ( <== 的確是
'id' => 1,
)
1st shift: array ( <== 且 shift 的確會返回第一列
'id' => 1,
)
count: 3 <== 且計數如預期維護
valid: false <== 但內部指標已超出有效範圍
current: NULL <== 因此目前值再次為 NULL
key: 0 <== 但我們仍然有一個有效的鍵
offsetGet(key): array ( <== 的確是
'id' => 2,
)
2nd shift: array ( <== 且 shift 的確會返回第一列
'id' => 2,
)
count: 2 <== 且計數如預期維護
valid: false <== 仍然無效等等...
current: NULL
key: 0
offsetGet(key): array (
'id' => 3,
)
rewinding... <== 現在倒帶
current: array ( <== 太棒了,有目前值
'id' => 3,
)
3rd shift: array ( <== shift 正常
'id' => 3,
)
count: 1 <== 計數正常
valid: true <== 哎呀,有效
current: NULL <== 沒有目前值
key: 0 <== 我們的鍵仍然有效 :o
offsetGet(key): array (
'id' => 4,
)
*/
?>

結論:我可能遺漏了一些關於 SplDoublyLinkedList::shift 為何一開始就沒有維護正確內部索引的資訊,但我發現更令人困惑的是,能夠在明顯有一個目前值的情況下,最終得到一個有效的 valid()、有效的 key(),但沒有 current()。

在 php 5.6.30 和 7.1.2 上測試,結果完全相同。
To Top