我目前正在研究一个通用表单创建类,昨天遇到了一个问题。我做了一个片段来重现这个问题。
本质上,我想在绘制整个组之后删除从原始元素数组中分组的元素,并且我在循环遍历元素数组时这样做。
代码片段应该涵盖问题,我在这里遗漏了什么吗?据我所知,在 foreach 中删除元素是完全安全和合法的,因为 foreach 在内部只使用了可以在循环期间修改的副本。
$ids = array('a' => array(), 'b' => array(), 'c' => array());
$groups['g1'] = array('a', 'c');
foreach($ids as $id => $element) {
//var_dump($ids);
$g_id = '';
// search the id in all groups
foreach($groups as $group_id => $group) {
if(in_array($id, $group)) {
$g_id = $group_id;
break;
}
}
// element is part of a group
if($g_id !== '') {
//echo $g_id;
// element a and c gets unset within loop and should not be in $ids anymore
foreach($groups[$g_id] as $field_id) {
unset($ids[$field_id]);
echo $field_id;
}
unset($groups[$g_id]);
} else {
if($id === 'a' || $id === 'c')
echo $id;
}
}
元素“c”在 foreach(groups ..) 循环中未设置,但随后再次在 else 分支中输出。此外,当我在开始时使用 var_dump($fields) 时,我总是在里面得到“a”、“b”和“c”。我正在使用 PHP 5.4.7。
提前致谢
编辑:我在示例代码中犯了一个错误,现在更新了。所有关于使用错误索引(本来应该是 0,1 等)的评论当然都是正确的。使用 var_dump 时的值现在未设置,但我仍然使用 'c' 进入 else 一次。
EDIT2:我没有完成原始代码,但在阅读了评论后,我目前对上面发布的代码片段提出了以下解决方案:
$ids=array("a"=>array(),"b"=>array(),"c"=>array(),"d"=>array(),"e"=>array());
$groups=array(array("a"),array("c", "e"));
array_walk($groups,function($v,$i)use(&$ids){
$in_both = array_intersect(array_keys($ids),$v);
//var_dump($in_both);
foreach($in_both as $b) {
unset($ids[$b]);
}
});
print_r($ids);
或者
$ids=array("a"=>array(),"b"=>array(),"c"=>array(),"d"=>array(),"e"=>array());
$groups=array(array("a"),array("c"));
array_walk($ids,function($v,$i)use(&$ids, $groups){
$in_both = array();
foreach($groups as $g) {
if(in_array($i,$g)) {
$in_both = array_intersect(array_keys($ids),$g);
}
}
foreach($in_both as $b) {
unset($ids[$b]);
}
});
print_r($ids);
在这种情况下,使用 foreach 对我不起作用,因为我需要在循环遍历它时更改 $ids 数组。
在最基本的情况下,代码如下:
$ids = array('a', 'b');
while(count($ids)) {
array_pop($ids);
echo 'pop';
}
echo 'empty';
尽管 foreach 可以更改数组中的原始值,但它不会更改用于迭代的数组副本,如 nl-x 已经说明的那样。感谢 Passerby 提出使用 array_walk 的想法。
EDIT3:更新的代码再次被剪断。尽管第二个剪断的行为也未定义。在迭代数组时从数组中删除元素似乎是个坏主意。