¿Cómo se elimina un elemento de matriz en un bucle foreach?

127

Quiero recorrer una matriz con foreachpara verificar si existe un valor. Si el valor existe, quiero eliminar el elemento que lo contiene.

Tengo el siguiente código:

foreach($display_related_tags as $tag_name) {
    if($tag_name == $found_tag['name']) {
        // Delete element
    }
}

No sé cómo eliminar el elemento una vez que se encuentra el valor. ¿Cómo lo elimino?

Tengo que usar foreachpara este problema. Probablemente hay alternativas foreach, y puedes compartirlas.

ajsie
fuente

Respuestas:

220

Si también obtiene la clave, puede eliminar ese elemento de esta manera:

foreach ($display_related_tags as $key => $tag_name) {
    if($tag_name == $found_tag['name']) {
        unset($display_related_tags[$key]);
    }
}
Gumbo
fuente
3
Información adicional sobre la optimización mediante el uso de $key => &$tag_name stackoverflow.com/a/2008893/922522
Justin
55
Tenga en cuenta que las matrices indexadas con elementos sin configurar pueden representarse como objetos en lugar de matrices después de a json_encode(). Puedes resolver esto $display_related_tags = array_values ($display_related_tags);después del foreachciclo.
Márton Tamás
Tenga en cuenta que el truco aquí es agregar un valor al bucle foreach ;-)
Mr Washington
55
Por favor, vea la respuesta @Neils. Encontrará errores inesperados, especialmente si trabaja con Array of stdClasses. ¿Te gusta el comportamiento inesperado? Yo no.
happy_marmoset
@happy_marmoset La respuesta de Neils no está ayudando. Fragmento $projects = array_filter($projects, function ($project) { return count($project->roles) > 0; });que convierte el resultado en objeto.
Paritosh
36

Una mejor solución es usar la array_filterfunción:

$display_related_tags =
    array_filter($display_related_tags, function($e) use($found_tag){
        return $e != $found_tag['name'];
    });

Como dice la documentación de php :

Como foreach se basa en el puntero de matriz interno en PHP 5, cambiarlo dentro del ciclo puede conducir a un comportamiento inesperado.

En PHP 7, foreach no usa el puntero interno de la matriz.

Neils
fuente
Tenga en cuenta que el tercer parámetro debe ser ARRAY_FILTER_USE_KEY para pasar la clave como $ e aquí.
namezero
@namezero OK, ¿por qué importa eso aquí?
AbraCadaver
@AbraCadaver De la documentación ( php.net/manual/en/function.array-filter.php ): ARRAY_FILTER_USE_KEY - pass key as the only argument to callback instead of the value ARRAY_FILTER_USE_BOTH - pass both value and key as arguments to callback instead of the value Default is 0 which will pass value as the only argument to callback instead. Dicho esto, leer la respuesta nuevamente en este caso, por supuesto, no importaría como usted afirma.
namezero
Importante Si está interesado en mantener la matriz como ordenada, debe llamar display_related_tags = array_values(display_related_tags);después.
guyaloni
9
foreach($display_related_tags as $key => $tag_name)
{
    if($tag_name == $found_tag['name'])
        unset($display_related_tags[$key];
}
Steve H
fuente
3
'desvincular' desvincula archivos, no tiene nada que ver con variables o, más específicamente, con matrices. ¿Tal vez te refieres a 'desarmado'?
amn
6

En lugar de hacer el bucle foreach () en la matriz, sería más rápido usar array_search () para encontrar la clave adecuada. En matrices pequeñas, usaría foreach para una mejor lectura, pero para matrices más grandes, o código ejecutado a menudo, esto debería ser un poco más óptimo:

$result=array_search($unwantedValue,$array,true);
if($result !== false) {
  unset($array[$result]);   
}

Se necesita el operador de comparación estricto! ==, porque array_search () puede devolver 0 como el índice de $ unwantedValue.

Además, el ejemplo anterior eliminará solo el primer valor $ unwantedValue, si $ unwantedValue puede aparecer más de una vez en $ array, debe usar array_keys (), para encontrarlos todos:

$result=array_keys($array,$unwantedValue,true)
foreach($result as $key) {
  unset($array[$key]);
}

Consulte http://php.net/manual/en/function.array-search.php para obtener más información.

PiotrN
fuente
0

Si tiene un escenario en el que debe eliminar más de un valor de la matriz foreach, en este caso debe pasar el valor por referencia para cada uno: intento explicar este escenario:

foreach ($manSkuQty as $man_sku => &$man_qty) {

               foreach ($manufacturerSkus as $key1 => $val1) {

  // some processing here and unset first loops entries                     
 //  here dont include again for next iterations
                           if(some condition)
                            unset($manSkuQty[$key1]);

                        }
               }
}

en el segundo bucle que desea desarmar, las entradas de los primeros bucles no vuelven a aparecer en la iteración para fines de rendimiento o, de lo contrario, también se desarman de la memoria porque en la memoria se presentan y vendrán en iteraciones.

Hassan Ali Shahzad
fuente
0

Ya hay respuestas que están dando luz sobre cómo desarmar. En lugar de repetir el código en todas sus clases, haga que funcione como se muestra a continuación y úselo en el código cuando sea necesario. En la lógica de negocios, a veces no desea exponer algunas propiedades. Consulte a continuación una llamada de línea para eliminar

public static function removeKeysFromAssociativeArray($associativeArray, $keysToUnset)
{
    if (empty($associativeArray) || empty($keysToUnset))
        return array();

    foreach ($associativeArray as $key => $arr) {
        if (!is_array($arr)) {
            continue;
        }

        foreach ($keysToUnset as $keyToUnset) {
            if (array_key_exists($keyToUnset, $arr)) {
                unset($arr[$keyToUnset]);
            }
        }
        $associativeArray[$key] = $arr;
    }
    return $associativeArray;
}

Llamar como:

removeKeysFromAssociativeArray($arrValues, $keysToRemove);
Somnath Muluk
fuente
-1

Como ya se mencionó, querría hacer un foreach con la clave y desarmarla usando la clave, pero tenga en cuenta que mutar una matriz durante la iteración es en general una mala idea, aunque no estoy seguro de las reglas de PHP sobre esto de improviso.

Ciarán Walsh
fuente
2
Un foreach php se ejecutará en toda la matriz independientemente. Pruebe desarmar un valor que es el siguiente en la iteración. Iterará en el desplazamiento, pero el valor será nulo.
Kevin Peno
Si no mutas una matriz durante la iteración, ¿cómo mutas una matriz? ¿Pueden ser malas foreacho forconstrucciones en lugar de iteraciones en general?
Gherman
Esto es más un comentario sobre otra respuesta que una respuesta en sí misma.
Sinister Beard