检测“实际”PHP中数组的结尾


Detecting the "actual" end of an array in PHP

假设我有一个数组如下:

$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);
}