删除array_walk()中回调函数中的行

时间:2014-10-15 08:19:24

标签: php arrays

我正在尝试使用array_walk()函数使用数组:

<?php

$array = array('n1' => 'b1', 'n2' => 'b2', 'n3' => 'b3');

array_walk($array, function(&$val, $key) use (&$array){
    echo $key."\n";
    if ($key == 'n1')
        $val = 'changed_b1';
    if ($key == 'n2' || $key == 'n3') {
        unset($array[$key]);
    }
});

print_r($array);

得到:

n1
n2
Array
(
    [n1] => changed_b1
    [n3] => b3
)

看来,删除第2个元素后的内容 - 第3个元素不被发送回回函数。

5 个答案:

答案 0 :(得分:8)

使用array_filter:

<?php
$filtered = array_filter($array, function($v,$k) {
    return $k !== "n2" && $k !== "n3";
}, ARRAY_FILTER_USE_BOTH);
?>

请参阅http://php.net/array_filter

答案 1 :(得分:5)

你可以做的是使用一个辅助数组,它会产生这些节点被删除的效果,比如;

<?php

$array = array('n1' => 'b1', 'n2' => 'b2', 'n3' => 'b3');

$arrFinal = array();
array_walk($array, function($val, $key) use (&$array, &$arrFinal){
    echo $key."\n";
    if ($key == 'n2' || $key == 'n3') {
        //Don't do anything
    } else {
       $arrFinal[$key] = $val;
    }
});

print_r($arrFinal);

https://eval.in/206159

答案 2 :(得分:0)

来自the documentation

  

只有数组的值可能会被更改; 结构不能改变,即程序员无法添加,取消设置或重新排序元素。如果回调不符合此要求,则此函数的行为未定义,并且不可预测

可能是您没有通过代码获得所需输出的原因。希望它有所帮助。

可能的替代方案:

  1. 如果您仍想使用array_walk(),只需创建一个新数组并复制所需的&#39;元素,即您不希望删除到新数组中的索引。如果要删除的元素数量非常大,则这是首选替代方案。
  2. 您可以查看array_filterarray_map,两者都依赖于将callback应用于数组的每个元素。你可以简单地在这个回调函数中设置一个禁止你想要删除的索引的条件。如果您要删除的元素数量很少,这将有效。
  3. 但是,如果要删除的元素是连续的并形成一个&#39;部分&#39;一个数组(在你的情况下,你想删除相邻的n2和n3)。您可以使用函数array_splice
  4. Sidenote - 我没有插入任何代码片段,因为我已将相关文档链接起来并开始使用它们本身应该是一个很好的练习。

答案 3 :(得分:0)

我意识到这已经有好几年了,但是我在寻找解决类似情况的方法时找到了线索。

我最终使用preg_grep仅返回我想遍历的数组,以防万一有人发现它有用。

因此,就我而言,我想忽略带有“。”的scandir数组中的文件。前缀(系统文件),然后对其余文件应用新的前缀。

这就是我想到的:

$fl = array_map(function($i){
    return $new_prefix . "/" . $i;
}, preg_grep("/^[^\.]/", scandir($path)));

如果您可以构建正则表达式以排除不需要的数组元素,则此解决方案应该有效。

答案 4 :(得分:0)

检查“array_walk”源代码,你会看到。 array_walk 使用 pos 来获取 item,并且在每个循环中,pos 向前移动。

    do {
    /* Retrieve value */
    zv = zend_hash_get_current_data_ex(target_hash, &pos);
    

    /* Retrieve key */
    zend_hash_get_current_key_zval_ex(target_hash, &args[1], &pos);

    /* Move to next element already now -- this mirrors the approach used by foreach
     * and ensures proper behavior with regard to modifications. */
    zend_hash_move_forward_ex(target_hash, &pos);

    /* Back up hash position, as it may change */
    EG(ht_iterators)[ht_iter].pos = pos;

并重置 pos 以获取价值

    /* Reload array and position -- both may have changed */
    if (Z_TYPE_P(array) == IS_ARRAY) {
        pos = zend_hash_iterator_pos_ex(ht_iter, array);
        target_hash = Z_ARRVAL_P(array);
    } else if (Z_TYPE_P(array) == IS_OBJECT) {
        target_hash = Z_OBJPROP_P(array);
        pos = zend_hash_iterator_pos(ht_iter, target_hash);
    } else {
        php_error_docref(NULL, E_WARNING, "Iterated value is no longer an array or object");
        result = FAILURE;
        break;
    }  
  • 如果键= n1;然后下一个位置 1
  • 如果键= n2;然后下一个位置 2
  • 如果键= n3;然后下一个位置 3

当运行 [$key == 'n2'] 时,下一个 pos 是 2 ; unset 后,位置 2 不可到达,所以循环结束。

所以实际上,那么 $key=='n3' 不会发生,你会得到结果。