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

时间:2011-08-04 05:25:44

标签: php arrays null comparison iteration

鉴于我有一个如下数组:

$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()

没有万无一失的方法可以准确地确定数组指针是否已经移过数组末尾,无论数组元素值是什么( null0等等。

买者;当然,使用临时变量存在大量的解决方案,但这种操作只需要肮脏和愚蠢。我很惊讶没有简洁的解决方案。


嗯,这绝不是一个完美的解决方案,因为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);
}

4 个答案:

答案 0 :(得分:5)

  

http://www.php.net/next
  注意:您将无法区分数组的结尾与布尔FALSE元素。要正确遍历可能包含FALSE元素的数组,请参阅each()函数。

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

each返回一个数组或false。这是非常独特的区别。

答案 1 :(得分:4)

获得元素数量的错误是什么?并使用它来检测我是否在最后一个元素? 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 :)";
}

答案 2 :(得分:0)

嗯,这就是我最终的目标:

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

无论如何,如果您有更好的解决方案,请随时回答。这很有效,但我很乐意接受更好的事情。

答案 3 :(得分:0)

提供你的答案,这是另一种方法,允许在实际循环之外进行独立测试。此测试不会影响内部数组指针。

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