Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/250.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 删除数组_walk()中回调函数中的行_Php_Arrays - Fatal编程技术网

Php 删除数组_walk()中回调函数中的行

Php 删除数组_walk()中回调函数中的行,php,arrays,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

我尝试使用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);
看起来,删除第二个元素后——第三个元素不会被发送到回调函数

来自:

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

这可能就是为什么您的代码不能获得所需输出的原因。希望能有帮助

可能的替代方案:

  • 如果仍要使用
    array\u walk()
    ,只需创建一个新数组,并将“必需”元素(即不希望删除的索引)复制到新数组中即可。如果要删除的元素数量非常大,这是首选的替代方案
  • 您可以查看或,两者都依赖于对数组的每个元素应用
    回调。您可以简单地在那里设置一个条件,禁止在此回调函数中删除索引。如果要删除的元素数量非常少,这将起作用
  • 但是,如果要删除的元素是连续的,并且形成数组的“部分”(在您的示例中,您希望删除相邻的n2和n3)。您可以使用该函数

  • 旁注-我没有加入任何代码片段,因为我已经链接了相关文档,开始使用它们本身应该是一个很好的练习。

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

    <?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);
    
    使用数组过滤器:

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

    参见

    我意识到这已经有好几年的历史了,但我在寻找类似情况的解决方案时发现了这条线索

    最后,我使用preg_grep只返回我想要遍历的数组,以防有人发现它有用

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

    以下是我的结论:

    $fl = array_map(function($i){
        return $new_prefix . "/" . $i;
    }, preg_grep("/^[^\.]/", scandir($path)));
    
    如果您可以构建一个正则表达式来排除不需要的数组元素,那么这个解决方案应该可以工作。

    检查“array\u walk”源代码,您将看到。array_walk使用pos获取项目,在每个循环中,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;
        }  
    
    • 如果key=n1;然后下一个位置1
    • 如果键=n2;然后下一个位置2
    • 如果键=n3;然后下一个位置3
    当运行[$key=='n2']时,下一个pos为2;取消设置后,无法到达位置2,因此循环结束


    因此,实际上,$key=='n3'将不会发生,而u将得到结果。

    手册中有一个关于更改结构/取消设置thru array walk函数的重要说明,@Ghost,有没有解决问题的建议?请查看下面hd的答案,或者为什么不直接使用foreach?实际上,这段代码非常复杂,如果您只想得到一个没有特定键的数组,请使用unset($array[“n2”],$array[“n3”]);当您添加了一个很好的解释(从手册中引用)时,请使用另一个选项作为备份well@mochalygin,请参阅我的更新答案,以了解可能的替代方案。希望它能让您从正确的方向开始。值得一提的是,它适用于PHP>=5.6。x@m6w6,需要更改一些元素并取消设置一些元素--这样
    array\u filter()
    can;这似乎是一个累赘,但如果没有其他建议,我会接受的。
        /* 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;
        }