【发布时间】:2013-04-11 06:04:30
【问题描述】:
我目前正在研究一个通用的表单创建类,昨天遇到了一个问题。 我做了一个 sn-p 来重现这个问题。
本质上,我想在绘制整个组之后删除从原始元素数组中分组的元素,并且我在循环遍历元素数组时这样做。
代码 sn-p 应该可以解决问题,我在这里遗漏了什么吗?据我所知,在 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。
提前致谢
编辑:我在示例代码中犯了一个错误,现在已更新。所有关于使用错误索引的 cmets(本来应该是 0,1 等)当然都是正确的。 使用 var_dump 时的值现在未设置,但我仍然使用 'c' 进入 else 一次。
编辑2: 我没有完成原始代码,但是在阅读了 cmets 之后,我目前对上面发布的代码 sn-p 提出了以下解决方案:
$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 的想法。
编辑3: 更新的代码再次被剪断。尽管第二个剪断的行为也未定义。在迭代数组时从数组中删除元素似乎是个坏主意。
【问题讨论】:
-
看here。我建议改用
for循环。 -
$ids[$field_id]在您的示例中不存在,因为它将解释为$ids["a"],而不是$ids[0]。另外,我很难回答你的问题,你介意让它更清楚一点,比如“我有两个看起来像这样 [数组代码] 的数组,我想删除 if...这样以后可以看起来像这样[数组代码]。”? -
@Passerby 优秀的观察+1。但是该错误不会改变输出中的任何内容。如果您将
$ids = array('a', 'b', 'c');更改为$ids = array('a'=>'a', 'b'=>'b', 'c'=>'c');,则不会发生任何变化。 -
@nl-x 正如我所说,我不太了解 OP 的问题/逻辑。我发现这个错误只是因为它有点明显。
-
@nl-x:这里真正的问题不是改变输出,而是取消设置数组元素。