假设我有一个数组如下:
$array = array('a', 'b', 0, 'c', null, 'd');
现在,我可以很容易地通过foreach
迭代它:
foreach($array as $value){
var_dump($value);
}
一切都很好。然而,如果我想做一个"peek"来看看我是否在最后一个元素上,下面的操作将不起作用:
reset($array);
while($value = current($array)){
var_dump($value);
if(next($array)){
// this won't be accurate because of the 0 element
}
}
好的,所以我做了一个更严格的测试:
if(null !== next($array)){
// this STILL won't be accurate because of the null element
}
是唯一的解决方案,使用索引for
循环与算术窥视?我不认为这对于维护关联键完整性是可行的,而不需要大量的浪费。(我知道我的例子并没有说明这个警告,但我会将current()
换成each()
, next()
换成current()
)
不管数组元素的值( null
, 0
等)
警告;当然,有很多使用临时变量的解决方案存在,但是对于这个操作来说,需要这样的事情似乎既肮脏又愚蠢。
好吧,这绝不是一个完美的解决方案,因为注意但是这里是:array_keys()
正在创建一个新的数组
$array = array('alpha', 'b' => 'beta', null, 'g' => 'gamma', false, 0, 'delta', null);
list($end) = array_keys(array_slice($array, -1, 1, true));
foreach($array as $key => &$value){
// do important stuff on each element
if($key !== $end){
// do important stuff on all but last element
}
}
注意我交换了array_slice()
和array_keys()
,所以没有创建完整的键拷贝。它最初是:array_slice(array_keys($array), -1);
,似乎修订将在内存上更好。
另一个编辑为那些绊倒在这里;这些可以在类似的情况下使用:
// each returns the current element, but assigns to the referenced arguments
// the "peeked" values. they're missing checks, but it's a start.
function peek(Array &$array, &$value){
$value = next($array);
return prev($array);
}
function peek_key(Array &$array, &$key){
next($array);
$key = key($array);
return prev($array);
}
function peek_each(Array &$array, &$key, &$value){
next($array);
list($key, $value) = array(key($array), current($array));
return prev($array);
}
http://www.php.net/next
注意:您将无法区分数组的结尾和布尔FALSE
元素。要正确遍历可能包含FALSE
元素的数组,请参见each()
函数。
while (list($key, $val) = each($fruit)) {
echo "$key => $val'n";
}
each
返回一个数组或false
。这是唯一可区分的
获得元素数量计数有什么问题?用它来检测我是否在最后一个元素上?http://codepad.org/zTRRjLdl
$myArr = $array = array('a', 'b', 0, 'c', null, 'd');
$count = count($myArr);
$index = 0;
foreach($myArr as $value)
{
var_dump($value);
$index++;
if($index == $count)
echo "Its the last one here :)";
}
嗯,这就是我最后的结果:
$array = array('alpha', 'b' => 'beta', null, 'g' => 'gamma', false, 0, 'delta', null);
if(!empty($array)){
list($end) = array_keys(array_slice($array, -1, 1, true));
foreach($array as $key => &$value){
// do important stuff on each element
if($key !== $end){
// do important stuff on all but last element
}
}
}
无论如何,如果你有更好的解决方案,请随意回答。这是有效的,但我很乐意接受任何更好的。
根据您的回答,这里有另一种方法,允许在实际循环之外进行独立测试。该测试不影响内部数组指针。
$arr = array('alpha', 'b' => 'beta', null, 'g' => 'gamma', false, 0, 'delta', null);
if (!empty($arr)) {
while (TRUE) {
// advance and rewind the internal array pointer to do useful things
// (note that this example doesn't cover rewinding the internal array
// pointer too far)
if (array_end($arr)) {
break;
}
}
}
/**
* Detect the end of an array
* @return boolean TRUE if we've reached the end of the array or exceeded its bounds
*/
function array_end(array $arr) {
$currentKey = key($arr);
if (NULL === $currentKey) {
// we've moved beyond the bounds of the array
return TRUE;
}
$lastKey = key(array_slice($arr, -1, 1, TRUE));
return ($currentKey === $lastKey);
}