注意:如果您的第一個元素為 false,您不會知道它是空的還是非空的。
<?php
$a = array();
$b = array(false, true, true);
var_dump(reset($a) === reset($b)); //bool(true)
?>
所以不要指望 false 傳回值代表是空陣列。
(PHP 4, PHP 5, PHP 7, PHP 8)
reset — 將陣列的內部指標設定到其第一個元素
array
輸入的陣列。
傳回陣列第一個元素的值,如果陣列為空,則傳回 false
。
版本 | 描述 |
---|---|
8.1.0 | 在 物件 上呼叫此函式已棄用。請先使用 get_mangled_object_vars() 將 物件 轉換為 陣列,或改用實作 Iterator 的類別所提供的方法,例如 ArrayIterator。 |
7.4.0 | SPL 類別的實例現在被視為沒有屬性的空物件,而不是呼叫與此函式同名的 Iterator 方法。 |
範例 1 reset() 範例
<?php
$array = array('step one', 'step two', 'step three', 'step four');
// 預設情況下,指標位於第一個元素
echo current($array) . "<br />\n"; // "step one"
// 跳過兩個步驟
next($array);
next($array);
echo current($array) . "<br />\n"; // "step three"
// 重設指標,從 step one 重新開始
reset($array);
echo current($array) . "<br />\n"; // "step one"
?>
注意:如果您的第一個元素為 false,您不會知道它是空的還是非空的。
<?php
$a = array();
$b = array(false, true, true);
var_dump(reset($a) === reset($b)); //bool(true)
?>
所以不要指望 false 傳回值代表是空陣列。
由於 reset() 除了重設其內部指標外,還會傳回陣列的第一個「值」;當它與 key() 結合使用或單獨使用時,它會傳回不同的結果。像是;
<?php
$products = array(
'biscuits' => array('biscuit1' => 'cobis', 'biscuit2' => 'probis'),
'chocolates' => array('coco1' => 'cococ', 'coco2' => 'prococ'),
);
echo key(reset($products['biscuits'])); // 嚴重錯誤
reset($products['biscuits']);
echo key($products['biscuits']); // 將列印 'biscuit1'
?>
這完全正常,因為在第一種方法中,reset() 傳回 'biscuits' 元素的第一個「值」,也就是 "cbosi"。因此,key(string) 會導致嚴重錯誤。而在第二種方法中,您只是重設了陣列,並未使用傳回值;相反地,您重設了指標,然後擷取了陣列的第一個鍵。
如果您的陣列有更多維度,可能不會導致嚴重錯誤,但當您結合 reset() 和 key() 或連續使用它們時,您會得到不同的結果。
關於取得陣列的第一個鍵,先 RESET 再 KEY 會比 ARRAY_KEYS 的 RESET 結果有效率得多(如 gardnerjohng at gmail dot com 所建議)。
<?php
reset($someArray);
echo key($someArray);
?>
這會給出相同的結果,但速度快得多。陣列越大,效能越好。在 100 個元素的長陣列上測試,結果快了 16 倍。
回應 gardnerjohng 取得陣列第一個 _key_ 的註解
若要取得陣列的第一個 _key_,您可以使用 reset() 和 key() 的組合。
<?php
$properties = array(
'colour' => 'grey',
'flavour' => 'rubber',
'name' => 'Mouse Ball',
'texture' => 'rubbery'
);
reset($properties);
echo key($properties); // => 'colour'
?>
我偏好這個解決方案,因為您不必建立 keys 陣列。這應該(未經測量)可以提高大型陣列的效能。
請注意,這裡您不能使用指標。在這種情況下,它會重設迭代計數器。
foreach($array as $key=>&$value) {...}
請改用標準的 foreach
foreach($array as $key=>$value) {...}
此外,以這種方式重設多維陣列也是個好方法
reset($voo2['moder']);
while (list($key, $value) = each ($voo2['moder'])) {
reset($voo2['moder'][$key]);
while (list($key1, $value1) = each ($voo2['moder'][$key])) {
#do what u want
}
}
請注意,reset() 不會影響多維陣列的子陣列。
例如:
<?php
$arr = array(
1 => array(2,3,4,5,6),
2 => array(6,7,8,9,10)
);
while(list($i,) = each($arr))
{
echo "IN \$arr[$i]<br>";
while(list($sub_i,$entry) = each($arr[$i]))
{
echo "\$arr[$i][$sub_i] = $entry<br>";
}
}
reset($arr);
// 再做一次
while(list($i,) = each($arr))
{
echo "IN \$arr[$i]<br>";
while(list($sub_i,$entry) = each($arr[$i]))
{
echo "\$arr[$i][$sub_i] = $entry<br>";
}
}
?>
將會印出
IN $arr[1]
$arr[1][0] = 2
$arr[1][1] = 3
$arr[1][2] = 4
$arr[1][3] = 5
$arr[1][4] = 6
IN $arr[2]
$arr[2][0] = 6
$arr[2][1] = 7
$arr[2][2] = 8
$arr[2][3] = 9
$arr[2][4] = 10
IN $arr[1]
IN $arr[2]
資訊
以下程式碼在 5.4.45 中會產生嚴格警告
return reset(array_keys($result['node']));
"嚴格警告:只能將變數以參考方式傳遞"
所以應該是
$keys = array_keys($result['node']);
return reset($keys);
請勿使用 `reset()` 來取得關聯陣列的第一個值。它對於真正的陣列來說效果很好,但在 Iterator 物件上卻會產生意料之外的結果。 http://bugs.php.net/bug.php?id=38478
Colin,我認為有更好的方法可以解決你的問題。
<?
// ...
foreach($a as $k => &$d){} // 請注意 "&"
// ...
?>
這是 PHP5 中使用 foreach 迴圈中的參考的新功能。這樣 PHP 就不會複製陣列,因此內部指標不會被重設。
我遇到 PHP 5.0.5 無故重設陣列子陣列的問題。問題在於對父陣列執行 foreach() 時,PHP 會複製子陣列,並且在複製時會重設原始陣列的內部指標。
以下程式碼示範了子陣列的重設
<?
$a = array(
'a' => array(
'A', 'B', 'C', 'D',
),
'b' => array(
'AA', 'BB', 'CC', 'DD',
),
);
// 將 $a 的指標設定為 'b',並將 'b' 的指標設定為 'CC'
reset($a);
next($a);
next($a['b']);
next($a['b']);
next($a['b']);
var_dump(key($a['b']));
foreach($a as $k => $d)
{
}
var_dump(key($a['b']));
?>
兩個 var_dump 的結果分別為 3 和 0。顯然 $a['b'] 的內部指標是透過對 $a 執行 foreach 迴圈而重設的。
每次 foreach 迴圈迭代 $a 的 'a' 和 'b' 鍵時,它都會將 $a['a'] 和 $a['b'] 的副本複製到 $d 中,這會重設 $a['a'] 和 $a['b'] 的內部指標,儘管沒有進行明顯的變更。
解決方案是改為迭代 $a 的鍵。
<?
foreach(array_keys($a) as $k)
{
}
?>
並使用 $a[$k](或建立 $a[$k] 的別名 $d 並處理使用別名所造成的後果)。
對於好奇的人,我正在一個虛擬物件上實作 Iterator 介面,並呼叫全域物件來執行實際的迭代(也是為了應對 PHP 缺乏 C 風格的指標,當對物件執行 $a = $b 時,如果修改 $a,會導致 $a 中的資料與 $b 中的資料不一致)。由於我有很多代表不同資料集的虛擬物件,我選擇將每個資料集儲存為全域物件中包含的子陣列。為了使此方法生效,每個虛擬物件都必須儲存一個鍵(可以自由重複而不會有問題),當在虛擬物件上呼叫 rewind、key、current、next 和 valid 時,它會將該鍵傳遞給全域物件。
不幸的是,對我來說,我的鍵需要不僅僅是一個簡單的字串或數字(如果是這樣,則可以用來直接索引該物件的資料子陣列,並避免問題),而是一個字串陣列。相反,我必須迭代(使用 foreach 迴圈)每個子陣列,並將鍵與儲存在子陣列中的變數進行比較。
因此,以這種方式使用 foreach 迴圈,加上 PHP 重設子陣列的指標,最終導致無限迴圈。
實際上,這可以透過 PHP 在複製後仍維護陣列的內部指標來解決。