¿Cómo eliminar un objeto de la matriz dentro del bucle foreach?

140

Recorro una matriz de objetos y quiero eliminar uno de los objetos en función de su propiedad 'id', pero mi código no funciona.

foreach($array as $element) {
    foreach($element as $key => $value) {
        if($key == 'id' && $value == 'searched_value'){
            //delete this particular object from the $array
            unset($element);//this doesn't work
            unset($array,$element);//neither does this
        } 
    }
}

Alguna sugerencia. Gracias.

ababa
fuente

Respuestas:

233
foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        if($valueKey == 'id' && $value == 'searched_value'){
            //delete this particular object from the $array
            unset($array[$elementKey]);
        } 
    }
}
prodigitalson
fuente
62
¿Es seguro eliminar un elemento de una matriz dentro de un bucle foreach de la misma matriz?
Olivier Pons
25
@Oliver: generalmente generará un comportamiento inesperado, pero puede hacerlo de manera segura con foreach en php. Lea aquí para una prueba: php.net/manual/en/control-structures.foreach.php#88578
pangon
1
@ Paritosh Sé que publicaste esto hace mucho tiempo, pero es porque PHP usa matrices asociativas. Entonces tiene un índice que se elimina: y se codifica en JSON como un Objeto. Tiene sentido, ya que una matriz asociativa es un "diccionario". Podría ayudar a alguien que viene.
Ryan O'Donnell
1
¿Realmente necesitas hacer el segundo para cada uno? ¿no puedes simplemente consultar la propiedad 'id' deseada del objeto? ¿Por qué revisar todos los otros accesorios?
htafoya
3
@htafoya no, solo podrías hacerlo if(isset($element['id']) && $element['id'] == 'searched_value') { unset($array[$elementKey]); }, creo que en el momento en que acabo de copiar y modificar su código para mostrarle cómo hacerlo unsetcorrectamente.
prodigitalson
2

Parece que su sintaxis para desarmar no es válida, y la falta de reindexación puede causar problemas en el futuro. Ver: la sección sobre matrices PHP .

La sintaxis correcta se muestra arriba. También tenga en cuenta los valores de matriz para reindexar, de modo que nunca indexe algo que eliminó anteriormente.

pablo.meier
fuente
2

También puede usar referencias en foreachvalores:

foreach($array as $elementKey => &$element) {
    // $element is the same than &$array[$elementKey]
    if (isset($element['id']) and $element['id'] == 'searched_value') {
        unset($element);
    }
}
air-dex
fuente
9
$ element (utilizado dentro y fuera del foreach) es solo una referencia a cada elemento de la matriz. unset ($ element) simplemente romperá la referencia, no destruye el elemento referenciado de su matriz.
Nicholas
3
@Dev_NIX $element = nullNO funcionaría, la longitud de los $arrayrestos sigue siendo la misma, solo contendría nulos
Nico Westerdale
1

Esto debería funcionar.....

reset($array);
while (list($elementKey, $element) = each($array)) {
    while (list($key, $value2) = each($element)) {
        if($key == 'id' && $value == 'searched_value') {
            unset($array[$elementKey]);
        }
    }
}
Josh
fuente
1

Ten cuidado con la respuesta principal.

con

[['id'=>1,'cat'=>'vip']
,['id'=>2,'cat'=>'vip']
,['id'=>3,'cat'=>'normal']

y llamando a la función

foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        if($valueKey == 'cat' && $value == 'vip'){
            //delete this particular object from the $array
            unset($array[$elementKey]);
        } 
    }
}

vuelve

[2=>['id'=>3,'cat'=>'normal']

en vez de

[0=>['id'=>3,'cat'=>'normal']

Esto se debe a que unset no vuelve a indexar la matriz.

Se reindexa. (si lo necesitamos)

$result=[];
foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        $found=false;
        if($valueKey === 'cat' && $value === 'vip'){
            $found=true;
            $break;
        } 
        if(!$found) {
           $result[]=$element;
        }
    }
}
magallanes
fuente
0

No soy un gran programador de php, pero puedo decir que en C # no se puede modificar una matriz mientras se itera a través de ella. Es posible que desee intentar usar su bucle foreach para identificar el índice del elemento, o elementos para eliminar, luego elimine los elementos después del bucle.

Corey Sunwold
fuente
14
Si bien es una mala práctica en la mayoría de los idiomas, las matrices en PHP son básicamente matrices asociativas que se pueden iterar en orden. Eliminar un elemento anterior no cambia las claves de los elementos que le siguen.
Ignacio Vazquez-Abrams
22
En realidad, está permitido porque la matriz que foreach usa internamente es una copia de la matriz original. De esa manera, modificar la matriz original es perfectamente seguro.
Juan
68
En realidad, está permitido porque php está jodido como el infierno.
Eric G