PHP Conference Japan 2024

each

(PHP 4, PHP 5, PHP 7)

each從陣列中返回目前的鍵值對並將陣列指標向前移動

警告

此函式自 PHP 7.2.0 起已棄用,並自 PHP 8.0.0 起已移除。強烈建議不要依賴此函式。

說明

each(array|object &$array): array

從陣列中返回目前的鍵值對並將陣列指標向前移動。

each() 執行後,陣列指標將會停留在陣列的下一個元素,或如果到達陣列結尾,則會超出最後一個元素。如果想再次使用 each 遍歷陣列,則必須使用 reset()

參數

array

輸入的陣列。

傳回值

從陣列 array 傳回目前的鍵值對。此對以一個四個元素的陣列返回,其鍵為 01keyvalue。元素 0key 包含陣列元素的鍵名,而 1value 包含資料。

如果陣列的內部指標超出陣列內容的結尾,則 each() 會傳回 false

範例

範例 #1 each() 範例

<?php
$foo
= array("bob", "fred", "jussi", "jouni", "egon", "marliese");
$bar = each($foo);
print_r($bar);
?>

$bar 現在包含以下鍵值對

Array
(
    [1] => bob
    [value] => bob
    [0] => 0
    [key] => 0
)

<?php
$foo
= array("Robert" => "Bob", "Seppo" => "Sepi");
$bar = each($foo);
print_r($bar);
?>

$bar 現在包含以下鍵值對

Array
(
    [1] => Bob
    [value] => Bob
    [0] => Robert
    [key] => Robert
)

each() 通常與 list() 一起使用來遍歷陣列,以下是一個範例

範例 #2 使用 each() 遍歷陣列

<?php
$fruit
= array('a' => 'apple', 'b' => 'banana', 'c' => 'cranberry');

reset($fruit);
while (list(
$key, $val) = each($fruit)) {
echo
"$key => $val\n";
}
?>

上面的範例會輸出

a => apple
b => banana
c => cranberry

注意

由於將陣列賦值給另一個變數會重設原始陣列的指標,如果我們在迴圈內將 $fruit 賦值給另一個變數,則上面的範例會導致無限迴圈。

警告

each() 也會接受物件,但可能會傳回非預期的結果。因此不建議使用 each() 迭代物件屬性。

參見

  • key() - 從陣列中取得鍵
  • list() - 將變數賦值為如同它們是一個陣列
  • current() - 傳回陣列中的目前元素
  • reset() - 將陣列的內部指標設定為其第一個元素
  • next() - 將陣列的內部指標向前移動
  • prev() - 將內部陣列指標倒回
  • foreach
  • 物件迭代

新增註解

使用者貢獻的註解 24 則註解

14
janhsh
2 年前
在 each() 函式過時之後,這裡提供一種修正原始碼的方式

如果您像這樣在 while 迴圈中使用 each()

while (list($Key,$Value)=@each($Array)){
....
}

您必須替換為

foreach ($Array as $Key => $Value){
....
}

同樣的想法。

while (list(,$Value)=@each($Array)){
....
}

將會變成

foreach ($Array as $Value){
....
}
41
wolfeym38 at yahoo dot com
17 年前
關於 foreach 與 while(list) = each 的速度
我寫了一個基準測試腳本,結果很明顯 foreach 更快。快很多。即使是大型陣列(尤其是大型陣列)。我測試了 100,000、1,000,000 和 10,000,000 的大小。為了對 1 千萬進行測試,我必須將記憶體限制設定得很高,它在實際運作時接近 1GB。總之,

<?php
function getDiff($start, $end) {
$s = explode(' ', $start);
$stot = $s[1] + $s[0];
$e = explode(' ', $end);
$etot = $e[1] + $e[0];
return
$etot - $stot;
}

$lim=10000000;
$arr = array();
for (
$i=0; $i<$lim; $i++) {
$arr[$i] = $i/2;
}

$start = microtime();
foreach (
$arr as $key=>$val);

$end = microtime();
echo
"time for foreach = " . getDiff($start, $end) . ".\n";

reset($arr);
$start = microtime();
while (list(
$key, $val) = each($arr));
$end = microtime();
echo
"time list each = " . getDiff($start, $end) . ".\n";
?>

以下是一些我的結果:使用 1,000,000
time for foreach = 0.0244591236115.
time list each = 0.158002853394.
desktop:/media/sda5/mpwolfe/tests$ php test.php
time for foreach = 0.0245339870453.
time list each = 0.154260158539.
desktop:/media/sda5/mpwolfe/tests$ php test.php
time for foreach = 0.0269000530243.
time list each = 0.157305955887.

然後使用 10,000,000
desktop:/media/sda5/mpwolfe/tests$ php test.php
time for foreach = 1.96586894989.
time list each = 14.1371650696.
desktop:/media/sda5/mpwolfe/tests$ php test.php
time for foreach = 2.02504014969.
time list each = 13.7696218491.
desktop:/media/sda5/mpwolfe/tests$ php test.php
time for foreach = 2.0246758461.
time list each = 13.8425710201.

順帶一提,這些結果是在我認為是 PHP 5.2 的版本,以及一台具有 3GB RAM 和 2.8GHz 雙核心 Pentium 的 Linux 機器上得到的。
17
phpcoder at gmail dot com
5 年前
each 被棄用是因為它暴露了太多內部實作細節,阻礙了語言的開發。(「我們不能做 X,因為它會破壞 each()。」)

https://wiki.php.net/rfc/deprecations_php_7_2#each

如果你想要一個陣列指標,請自己維護它。這可能也是個好主意,因為這樣它在程式碼中是可見的。
10
dmikam
3 年前
這個函式在 PHP 7.2.0 中被標記為已棄用,並在 PHP 8.0.0 中移除,舊程式碼的替代方案看起來會像這樣

function legacy_each($array){
$key = key($array);
$value = current($array);
$each = is_null($key) ? false : [
1 => $value,
'value' => $value,
0 => $key,
'key' => $key,
];
next($array);
return $each;
}
7
man13or at hotmail dot fr
4 年前
您好,由於 each() 和 list() 經常「背叛」非常舊的應用程式,我只是建議不要再使用它們了。

如果您想根據關聯陣列分配變數,
請將此替換

while(list ($key, $value) = each ($my_array)) {
$$key = $value;
}

為此

foreach ($my_array as $key => $value) {
$$key = $value;
}
12
sjoerd-php at linuxonly dot nl
18 年前
使用 foreach 而不是 while、list 和 each。foreach 更
- 更容易閱讀
- 更快
- 不受陣列指標的影響,因此不需要 reset()。

它的工作方式如下
<?php
$arr
= array('foo', 'bar');
foreach (
$arr as $value) {
echo
"The value is $value.";
}

$arr = array('key' => 'value', 'foo' => 'bar');
foreach (
$arr as $key => $value) {
echo
"Key: $key, value: $value";
}
?>
2
Henk Poley
5 年前
Rector 有一個自動修復程式('ListEachRector')可以遷移離開 `each()`

https://github.com/rectorphp/rector/blob/master/docs/AllRectorsOverview.md#listeachrector

如果你看一下程式碼範例,你會發現這甚至很容易用手動完成。
4
james at gogo dot co dot nz
20 年前
值得注意的是,陣列的參考沒有它們自己的陣列指標,而且取得陣列的參考並不會重置它的陣列指標,所以它的運作方式如你所預期的那樣,透過 each 取得陣列的前三項,而不是第一項 3 次。

<?php
$x
= array(1,2,3);

print_r(each($x));
echo
"\n";

$y =& $x;
print_r(each($y));
echo
"\n";

$z =& $y;
print_r(each($z));
echo
"\n";
?>
3
Sopinon
19 年前
如果你想顯示你陣列的完整結構(樹狀),那麼你可以使用這個遞迴解決方案。

<?PHP
$tree
= "";
array_tree($your_array);
echo
$tree;

// 遞迴函式
function array_tree($array, $index=0){
global
$tree;
$space="";
for (
$i=0;$i<$index;$i++){
$space .= " ";
}
if(
gettype($array)=="array"){
$index++;
while (list (
$x, $tmp) = each ($array)){
$tree .= $space."$x => $tmp\n";
array_tree($tmp, $index);
}
}
}
?>
2
Anonymous
6 年前
一個奇怪的棄用函式。如果你在 foreach 迴圈之外的集合中追蹤陣列指標,你就不會在意效能,而且這個函式的效用是核心的。

相反地,你必須呼叫兩個函式:current() 然後 next() 來複製它的行為。
2
michael k (編輯名稱已知)
17 年前
如果您想要迭代一個二維稀疏陣列,並且想要先顯示每個第一個元素,然後是每個第二個元素,依此類推,您可以使用這段程式碼

$fruits = array ( "fruits" => array ( "a" => "orange",
"b" => "banana",
"c" => "apple"
),
"numbers" => array ( 1,
2,
3,
4,
5,
6
),
"holes" => array ( "first",
5 => "second",
"third",
10 => "fourth",
)
);

$done = False;
while ($done == False) {
$done = True;

// 重要:&$val 必須是一個參考 (使用 &),
// 如果不使用,則 $val 的內部計數器將會
// 每次都被重新初始化,並且您將會永遠循環於第一個元素。
// for eternity.

foreach($fruits as $key => &$val) {

if (list($inner_key, $inner_val) = each(&$val)) {
$done = False;
echo "$key : : $inner_key => $inner_val <br> \n";
}

}
}

注意:這只是一個快速的技巧,如果您知道更好的方法,請貼出來!
1
wodzuY2k at anronet dot pl
22 年前
這個函式將幫助您將任何變數轉儲到 XML 結構中。

//將變數轉儲到簡單的 XML 結構
function var_dump_xml($tagname,$variable,$level=0)
{
for($i=0;$i<$level;$i++) $marg.=' ';
if (eregi('^[0-9].*$',$tagname)) $tagname='tag_'.$tagname; //XML 標籤不能以 [0-9] 字元開頭
if (is_array($variable))
{
echo $marg."<$tagname>\n";
while (list ($key, $val) = each ($variable)) var_dump_xml($key,$val,$level+1);
echo $marg."</$tagname>\n";
}
elseif (strlen($variable)>0)
{
echo $marg."<$tagname>".htmlspecialchars($variable)."</$tagname>\n";
};
};

/*
範例

$myVar = array("name"=>"Joe", "age"=>"26", "children"=>array("Ann","Michael"));
var_dump_xml("myVarTag",$myVar);
*/
1
matthew at mhalls dot net
19 年前
給 panania at 3ringwebs dot com

如果您確定您只收到一列,則 while 迴圈會是多餘的。為了縮短您的程式碼

$strSQL = "SELECT * FROM table WHERE id=1";
$RecordsetSelect = $db->runQuery ($strSQL);
list($key, $val) = mysql_fetch_row($RecordsetSelect);
echo "$key => $val\n";
mysql_free_result($RecordsetSelect);

在只返回一列的情況下,這是一個更優雅的解決方案,但本質上只是挑剔。它也展示了使用 list 的另一種快速方法。
-1
massimo dot modica at tin dot it
14 年前
如果您在每次使用 each() 之前忘記重置陣列,相同的程式碼在不同的 PHP 版本中可能會產生不同的結果。

<?php

$a
= array(1,2,3);

foreach (
$a AS $k => $v) $a[$k] = 2*$v;

while(list(
$k2, $v2) = each($a)) { echo($v2."\n"); }

?>

在 PHP 5.2.0 中

2
4
6

在 PHP 5.2.6 中

4
6
-1
匿名
22 年前
我通常處理大量的二維陣列。由於我曾經在正確地遍歷它們時遇到一些問題,也許有人也遇到過這些問題,並且可以使用這個方法。

它基於一個名為 $array[$x][$y] 的二維陣列。在某些 (但不是所有) (x,y) 的位置上,有一個我想要訪問的值。請注意,我事先不知道 $x 或 $y 的範圍(即它們的最高和最低值)。

while (list ($x, $tmp) = each ($array)) {
while (list ($y, $val) = each ($tmp)) {
echo "$x, $y, $val";
}
}

因此,每個 (x,y) 對的答案可以是(當然,前提是這些值事先在您的陣列中)

1, 1, 2
2, 2, 0
3, 1, 1
5, 2, 2
5, 1, 2

請注意,只會顯示具有相應值的 (x,y) 對。

堅持下去
Jon Egil Strand
NTNU
-2
amby2 at izh dot com
19 年前
我找到了一種使用 for 語句循環遍歷關聯陣列的簡潔方法(而不是像下面大多數範例那樣使用 while)。

<?php

for (reset($array); list($key) = each($array);) {
echo
$key;
echo
$array[$key];
}

?>

或者

<?php

for (reset($array); list($key, $value) = each($array);) {
echo
$key;
echo
$value;
echo
$array[$key];
}

?>

使用這樣的結構,您幾乎不會忘記新增 reset($array) 程式碼行。
-2
tk at turtle-entertainment dot de
23 年前
請務必使用內建函式 "unset();" 或 "reset();" - 很多人都忘記了這一點,並對建立的輸出感到疑惑!
-2
13975001197 at 163 dot com
6 年前
在 PHP 7.2 中,我們可以使用 foreach() 來取代 each(),例如

foreach($array as $key => $value) {
//做一些事情
}
-3
Gillis at dancrea dot com
22 年前
我寫了一個簡短而相當簡單的腳本,用於在關聯陣列中搜尋值,以下是一個簡化的範例

<?php

$foo
['bob'] = "bob is ugly";
$foo['bill'] = "bill is rich";
$foo['barbie'] = "barbie is cute";
$search = "rich";

echo
"正在搜尋陣列 foo 中是否有 $search:<br>";
reset ($foo);
while (list (
$key, $val) = each ($foo)) {
if (
preg_match ("/$search/i", $val)) {
print
"在 $key 中找到匹配項。<br />";
} else {
print
"在 $key 中未找到匹配項。<br />";
}
}

?>

將輸出
正在搜尋陣列 foo 中是否有 rich
在 bob 中未找到匹配項。
在 bill 中找到匹配項。
在 barbie 中未找到匹配項。
-3
php at omit dot ianco dot co dot uk
16 年前
我希望能夠在循環遍歷陣列時向其中新增元素。foreach 不允許這樣做,因為它正在使用陣列的秘密副本。each 使這成為可能(在 PHP 4 上測試)。
<?php
$shopping_list
= array('oysters', 'caviare');
reset ($shopping_list);
while (list(
$key, $value) = each ($shopping_list)) {
if (
$value == 'oysters') $shopping_list[] = 'champagne';
elseif (
$value == 'champagne') $shopping_list[] = 'ice';
}
print_r($shopping_list);
// 陣列 ( [0] => oysters [1] => caviare [2] => champagne [3] => ice )
?>
-5
gaviel
13 年前
好的,這是一個使用 foreach 迭代多維陣列的方法。

<?php
$members
= array(
"member1" => array (
"First Name" => "Robert",
"Last Name" => "Burton",
"Age" => "20"
),
"member2" => array (
"First Name" => "Cheska",
"Last Name" => "Vladesk",
"Age" => "21"
),
"member3" => array (
"First Name" => "Gino",
"Last Name" => "Marley",
"Age" => "19"
),
"member4" => array (
"First Name" => "Jake",
"Last Name" => "White",
"Age" => "16"
),
);
$dataSetCount = count($members);
echo
"<h1>共有 $dataSetCount 位成員</h1>";

$i = 0;
foreach (
$members as $each_members) {
$i++;
echo
"<h2>成員 $i</h2>";
foreach (
$each_members as $position => $details) {
echo
"<b>$position</b>" . ": " . $details . "<br />";
}
}
?>
-4
kris at angelanthony dot com
24 年前
請記得,如果使用 "each()" 多次迭代陣列,請使用 "reset()"!範例:

while(list($key,$value) = each($array)){
// 程式碼在這裡
}

現在,$array 的內部指標位於陣列的末端,如果再次嘗試像上面那樣的迭代,將會導致 "while" 區塊內的程式碼執行次數為零。您必須呼叫 "reset($array)" 來重置內部陣列指標,才能再次從第一個元素開始迭代陣列。
-5
nino dot skopac at gmail dot com
9 年前
<?php
function each_v2($arr) {
// 與 each() 相同,但當到達陣列末端時,會重置它
static $i = 0;

if (isset(
$arr[$i])) {
// 存在
return $arr[$i++];
} else {
// 重置 $i 為 0 並重複
$i = 0;
return
each_v2($arr);
}
}
?>
-5
ayyappan dot ashok at gmail dot com
8 年前
/* 通過 each() 迭代物件 */

class SAI
{
public function __toString()
{
return __CLASS__;
}
}
$a = new SAI();
$b = new SAI();
$c = new SAI();
$d = new SAI();
$e = new SAI();

$objarray = array($a,$b,$c,$d,$e);
reset($objarray);
while (list($key, $val) = each($objarray))
{
echo "$key => $val\n";
}
//結果
0 => SAI
1 => SAI
2 => SAI
3 => SAI
4 => SAI

警告
each() 也會接受物件,但可能會返回非預期的結果。因此,不建議使用 each() 迭代物件的屬性。
To Top