В настоящее время я работаю над общим классом создания форм и вчера имел проблему. Я сделал фрагмент, чтобы воспроизвести проблему.
По сути, я хочу удалить элементы, которые сгруппированы из массива исходных элементов после того, как вся группа была нарисована, и я делаю это, перебирая массив элементов.
Этот фрагмент кода должен охватывать проблему, я что-то упустил? По моим сведениям, удаление элемента в то время как 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.
заранее спасибо
EDIT: я ошибся в примере кода, теперь он обновлен. Разумеется, все комментарии об использовании неправильного индекса (это было бы 0,1 и т. Д.). Значения при использовании var_dump теперь не заданы, но я все равно попадаю в else с «c» один раз.
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", "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);
не$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';
Allthough foreach может изменять исходные значения из массива, он не изменит копию массива, используемого для итерации, как уже указано nl-x. Спасибо Passerby за идею использования array_walk для этого.
EDIT3: обновленный код снова отключен. Второй отрезанный allthough ведет себя также неопределенным. Удаление элементов из массива при итерации по нему кажется плохой идеей.