Eliminar matriz de PHP por valor (no clave)

Tengo una matriz de PHP de la siguiente manera:

$messages = [312, 401, 1599, 3, ...];

Quiero borrar el elemento que contiene el valor $del_val (por ejemplo, $del_val=401), pero no conozco su clave. Esto podría ayudar: cada valor solo puede estar allí una vez.

Estoy buscando la función más sencilla para realizar esta tarea, por favor.

preguntado el 28 de agosto de 11 a las 21:08

@Adam Strudwick Pero si tiene muchas eliminaciones en esta matriz, ¿sería mejor iterar una vez y hacer que su clave sea igual al valor? -

20 Respuestas

Usar array_search() y unset, intente lo siguiente:

if (($key = array_search($del_val, $messages)) !== false) {
    unset($messages[$key]);
}

array_search() devuelve la clave del elemento que encuentra, que se puede usar para eliminar ese elemento de la matriz original usando unset(). Volverá FALSE en caso de falla, sin embargo, puede devolver un valor falso-y en caso de éxito (su clave puede ser 0 por ejemplo), por lo que la comparación estricta !== se utiliza el operador.

La if() declaración comprobará si array_search() devolvió un valor y solo realizará una acción si lo hizo.

Respondido 18 Oct 17, 11:10

¿Funcionaría también $ messages = array_diff ($ messages, array ($ del_val))? ¿Sería mejor en rendimiento? - adam strudwick

@Adam ¿Por qué no probarlo? Mi sentimiento es que array_diff() sería más lento ya que es comparando dos matrices, no simplemente buscando a través de una como array_search(). - Bojangles

Aunque esto es válido, debe evitar asignar valores en declaraciones como esa. Solo te meterá en problemas. - Adlawson

Si el valor que está buscando tiene una clave de 0 o cualquier otro valor falso, no anulará el valor y su código no funcionará. Deberías probar $key === false. (editar- lo tienes) - evan

Tenga en cuenta que esto no restablecerá las claves de matriz. - montrealista

Bueno, eliminar un elemento de la matriz básicamente se establece diferencias con un elemento.

array_diff( [312, 401, 15, 401, 3], [401] ) // removing 401 returns [312, 15, 3]

Se generaliza muy bien, puede eliminar tantos elementos como desee al mismo tiempo, si lo desea.

Cláusula de exención de responsabilidades: Tenga en cuenta que mi solución produce una nueva copia de la matriz mientras mantiene la anterior intacta en contraste con la respuesta aceptada que muta. Elija el que necesita.

Respondido 19 Abr '19, 11:04

esto solo funciona para objetos que se pueden convertir en una cadena - nischayn22

Parece que recibo un 'Error de análisis' por decir [$element], Solía array($element) en lugar de. No es gran cosa, pero solo quería que cualquiera que tuviera un problema similar supiera que no estaba solo. Angad

Claro, he asumido que PHP 5.4 ahora es mayoritario para eliminar la antigua notación. Gracias por el comentario. - Rok Kralj

Vale la pena señalar que por alguna razón array_diff usos (string) $elem1 === (string) $elem2 como su condición de igualdad, no $elem1 === $elem2 como se podría esperar. El problema señalado por @ nischayn22 es una consecuencia de esto. Si desea usar algo como una función de utilidad que funcione para matrices de elementos arbitrarios (que pueden ser objetos), la respuesta de Bojangle podría ser mejor por esta razón. - marca amery

También tenga en cuenta que este método realiza una clasificación internamente para cada argumento a array_diff() y así empuja el tiempo de ejecución hasta O (n lg n) desde O (n). - Jack

Una forma interesante es usar array_keys():

foreach (array_keys($messages, 401, true) as $key) {
    unset($messages[$key]);
}

La array_keys() La función toma dos parámetros adicionales para devolver solo claves para un valor particular y si se requiere una verificación estricta (es decir, usar === para la comparación).

Esto también puede eliminar varios elementos de la matriz con el mismo valor (p. Ej. [1, 2, 3, 3, 4]).

Respondido el 14 de enero de 14 a las 06:01

Sí, esto es efectivo para seleccionar varios elementos / claves de matriz. - Oki Erie Rinaldi

Esto es lo mejor para matrices que pueden no contener todos los valores únicos. - Derokorian

El problema es que deja el índice de las claves ordenadas: [0] - a, [2] - b (el [1] se ha ido pero la matriz todavía lo pierde) - Rodniko

@Rodniko en cuyo caso necesitarías array_values() así como; Sin embargo, las claves restantes siguen en el mismo orden, por lo que técnicamente no está "desordenado". Jack

Si sabe con certeza que su matriz contendrá solo un elemento con ese valor, puede hacer

$key = array_search($del_val, $array);
if (false !== $key) {
    unset($array[$key]);
}

Sin embargo, si su valor puede aparecer más de una vez en su matriz, puede hacer esto

$array = array_filter($array, function($e) use ($del_val) {
    return ($e !== $del_val);
});

Nota: La segunda opción solo funciona para PHP5.3 + con cierres

Respondido 08 ago 14, 03:08

$fields = array_flip($fields);
unset($fields['myvalue']);
$fields = array_flip($fields);

Respondido 01 ago 12, 18:08

Esto solo funciona cuando su matriz no contiene valores duplicados que no sean los que está tratando de eliminar. - jberculo

@jberculo y, a veces, eso es exactamente lo que necesita, en algunos casos me ahorra hacer una matriz única en él también: oscuromukke

Tal vez, pero usaría funciones diseñadas específicamente para hacer eso, en lugar de ser solo un efecto secundario afortunado de una función que básicamente se usa y está destinada a otra cosa. También haría que su código sea menos transparente. - jberculo

El mensaje dice "cada valor solo puede estar allí una vez", esto debería funcionar. Sin embargo, habría sido bueno si el póster hubiera usado los nombres de las variables pequeñas y hubiera agregado una pequeña explicación: Raatje

aparentemente esto es más rápido en comparación con la solución seleccionada, hice una pequeña evaluación comparativa. - usuario1642018

La mejor manera es array_splice

array_splice($array, array_search(58, $array ), 1);

Reason for Best está aquí en http://www.programmerinterview.com/index.php/php-questions/how-to-delete-an-element-from-an-array-in-php/

Respondido el 26 de enero de 17 a las 06:01

Esto no funcionará en matrices asociativas y matrices que tengan espacios en sus claves, p. Ej. [1, 2, 4 => 3]. - Jack

No lo siento, esto funcionará. Por favor lea el artículo que he proporcionado enlace - Aireado

No lo hará. Considere la matriz de mi comentario anterior; después de que use su código para eliminar el valor 3, la matriz será [1, 2, 3]; en otras palabras, el valor no se eliminó. Para ser claros, no digo que falle en todos los escenarios, solo en este. - Jack

array_splice es el mejor método, unset no ajustará los índices de la matriz después de eliminar - Raaghu

O simplemente, de forma manual:

foreach ($array as $key => $value){
    if ($value == $target_value) {
        unset($array[$key]);
    }
}

Este es el más seguro de ellos porque tiene control total sobre su matriz

Respondido el 22 de Septiembre de 15 a las 20:09

Usar array_splice() en lugar de unset() también reordenará los índices de la matriz, lo que podría ser mejor en este caso. - daniela orlando

function array_remove_by_value($array, $value)
{
    return array_values(array_diff($array, array($value)));
}

$array = array(312, 401, 1599, 3);

$newarray = array_remove_by_value($array, 401);

print_r($newarray);

Salida

Array ( [0] => 312 [1] => 1599 [2] => 3 )

Respondido 29 ago 11, 03:08

No estoy seguro de si esto es más rápido ya que esta solución implica múltiples llamadas a funciones. - Julián Paolo Dayag

Las respuestas de solo código son de bajo valor en Stack Overflow. Cada respuesta debe incluir una explicación de cómo funciona o por qué cree que es un buen consejo frente a otras técnicas. - mickmackusa

Con PHP 7.4 usando funciones de flecha:

$messages = array_filter($messages, fn ($m) => $m != $del_val);

Para mantenerlo como una matriz no asociativa, envuélvalo con array_values():

$messages = array_values(array_filter($messages, fn ($m) => $m != $del_val));

Respondido 14 Abr '20, 17:04

tu puedes hacer:

unset($messages[array_flip($messages)['401']]);

Explicación: Elimina el elemento que tiene la clave 401 después de voltear la matriz.

Respondido el 21 de junio de 19 a las 07:06

Tienes que tener mucho cuidado si quieres preservar el estado. porque todo el código futuro tendrá que tener valores en lugar de claves. - Saadlulu

La matriz de mensajes de @saadlulu $ no se invertirá ya que array_flip () no afecta la matriz original, por lo que la matriz resultante después de aplicar la línea anterior será la misma, excepto que se eliminará el resultado no deseado. - Qurashi

No estoy seguro de si esto es correcto, ¿y si hay varios elementos con el valor de 401? - Zippp

Esto aún conservará las claves. - Szabolcs Páll

Para eliminar varios valores, pruebe este:

while (($key = array_search($del_val, $messages)) !== false) 
{
    unset($messages[$key]);
}

Respondido el 21 de junio de 19 a las 07:06

Esto será menos eficiente que recorrer la entrada una vez (y hay varias herramientas para hacer esto). Imagine que está iterando una matriz indexada con 10 elementos y desea eliminar los elementos en el índice 4 y 8. Esto iterará de 0 a 4, luego desarmará el elemento [4], luego iterará de 0 a 8, luego desarmará el elemento [ 8]. Vea cómo esta técnica verificará innecesariamente [0], [1], [2], [3] más de una vez. Nunca usaría esta técnica por ningún motivo y recomiendo que todos los investigadores tomen un punto de vista amplio a partir de esta respuesta. (esta es la razón de mi DV) - mickmackusa

La respuesta aceptada convierte la matriz en matriz asociativa, por lo que, si desea mantenerla como una matriz no asociativa con la respuesta aceptada, es posible que deba usar array_values

if(($key = array_search($del_val, $messages)) !== false) {
    unset($messages[$key]);
    $arr = array_values($messages);
}

La referencia es aquí

Respondido el 21 de junio de 19 a las 07:06

Tomó prestada la lógica de subrayado.JS _.reject y creó dos funciones (¡la gente prefiere funciones!)

array_reject_value: Esta función simplemente rechaza el valor especificado (también funciona para PHP4,5,7)

function array_reject_value(array &$arrayToFilter, $deleteValue) {
    $filteredArray = array();

    foreach ($arrayToFilter as $key => $value) {
        if ($value !== $deleteValue) {
            $filteredArray[] = $value;
        }
    }

    return $filteredArray;
}

matriz_rechazar: Esta función simplemente rechaza el método invocable (funciona para PHP> = 5.3)

function array_reject(array &$arrayToFilter, callable $rejectCallback) {

    $filteredArray = array();

    foreach ($arrayToFilter as $key => $value) {
        if (!$rejectCallback($value, $key)) {
            $filteredArray[] = $value;
        }
    }

    return $filteredArray;
}

Entonces, en nuestro ejemplo actual, podemos usar las funciones anteriores de la siguiente manera:

$messages = [312, 401, 1599, 3, 6];
$messages = array_reject_value($messages, 401);

o incluso mejor: (ya que esto nos da una mejor sintaxis para usar como el matriz_filtro uno)

$messages = [312, 401, 1599, 3, 6];
$messages = array_reject($messages, function ($value) {
    return $value === 401;
});

Lo anterior se puede usar para cosas más complicadas, como digamos que nos gustaría eliminar todos los valores que son mayores o iguales a 401, simplemente podríamos hacer esto:

$messages = [312, 401, 1599, 3, 6];
$greaterOrEqualThan = 401;
$messages = array_reject($messages, function ($value) use $greaterOrEqualThan {
    return $value >= $greaterOrEqualThan;
});

Respondido el 21 de junio de 19 a las 07:06

¿No es este filtro de reinvención? php.net/manual/en/function.array-filter.php - ricardo duerr

Sí, de hecho. Como ya digo en el post "o incluso mejor: (ya que esto nos da una mejor sintaxis para usar como la de array_filter)". A veces, realmente solo necesita que la función rechace como subrayado y en realidad es justo lo opuesto al filtro (y debe obtenerlo con la menor cantidad de código posible). Esto es lo que hacen las funciones. Esta es una forma sencilla de rechazar valores. - Juan Skoumbourdis

Sé que esto no es eficiente en absoluto, pero es simple, intuitivo y fácil de leer.
Entonces, si alguien está buscando una solución no tan elegante que pueda extenderse para trabajar con más valores o condiciones más específicas ... aquí hay un código simple:

$result = array();
$del_value = 401;
//$del_values = array(... all the values you don`t wont);

foreach($arr as $key =>$value){
    if ($value !== $del_value){
        $result[$key] = $value;
    }

    //if(!in_array($value, $del_values)){
    //    $result[$key] = $value;
    //}

    //if($this->validete($value)){
    //      $result[$key] = $value;
    //}
}

return $result

Respondido el 21 de junio de 19 a las 07:06

Si no conoce su clave, significa que no importa.

Puede colocar el valor como clave, lo que significa que encontrará el valor instantáneamente. Mejor que usar la búsqueda en todos los elementos una y otra vez.

$messages=array();   
$messages[312] = 312;    
$messages[401] = 401;   
$messages[1599] = 1599;   
$messages[3] = 3;    

unset($messages[3]); // no search needed

Respondido el 21 de junio de 19 a las 07:06

Solo funciona para objetos que se pueden convertir en una cadena. - Emile Bergeron

Un trazador de líneas usando el or operador:

($key = array_search($del_val, $messages)) !== false or unset($messages[$key]);

Respondido el 21 de junio de 19 a las 07:06

PHP 7.4 o superior

function delArrValues(array $arr, array $remove) {
    return array_filter($arr, fn($e) => !in_array($e, $remove));
};

Entonces, si tiene la matriz como

$messages = [312, 401, 1599, 3];

y quieres eliminar ambos 3, 312 desde la matriz $ messages, harías esto

delArrValues($messages, [3, 312])

Volvería

[401, 1599]

La mejor parte es que puede filtrar varios valores fácilmente, incluso si hay varias apariciones del mismo valor.

contestado el 20 de mayo de 21 a las 08:05

Según su requerimiento "cada valor solo puede estar ahí por una vez"si solo está interesado en mantener valores únicos en su matriz, entonces el array_unique() podría ser lo que estás buscando.

Entrada:

$input = array(4, "4", "3", 4, 3, "3");
$result = array_unique($input);
var_dump($result);

Resultado:

array(2) {
  [0] => int(4)
  [2] => string(1) "3"
}

Respondido el 21 de junio de 19 a las 07:06

Esta publicación DE NINGUNA MANERA responde a la pregunta del OP. Ésta es la respuesta correcta a otra pregunta. (esta es la razón de mi DV) - mickmackusa

esta respuesta no está relacionada con la pregunta - Zoltán Süle

Creo que la forma más sencilla sería usar una función con un bucle foreach:

//This functions deletes the elements of an array $original that are equivalent to the value $del_val
//The function works by reference, which means that the actual array used as parameter will be modified.

function delete_value(&$original, $del_val)
{
    //make a copy of the original, to avoid problems of modifying an array that is being currently iterated through
    $copy = $original;
    foreach ($original as $key => $value)
    {
        //for each value evaluate if it is equivalent to the one to be deleted, and if it is capture its key name.
        if($del_val === $value) $del_key[] = $key;
    };
    //If there was a value found, delete all its instances
    if($del_key !== null)
    {
        foreach ($del_key as $dk_i)
        {
            unset($original[$dk_i]);
        };
        //optional reordering of the keys. WARNING: only use it with arrays with numeric indexes!
        /*
        $copy = $original;
        $original = array();
        foreach ($copy as $value) {
            $original[] = $value;
        };
        */
        //the value was found and deleted
        return true;
    };
    //The value was not found, nothing was deleted
    return false;
};

$original = array(0,1,2,3,4,5,6,7,4);
$del_val = 4;
var_dump($original);
delete_value($original, $del_val);
var_dump($original);

La salida será:

array(9) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [2]=>
  int(2)
  [3]=>
  int(3)
  [4]=>
  int(4)
  [5]=>
  int(5)
  [6]=>
  int(6)
  [7]=>
  int(7)
  [8]=>
  int(4)
}
array(7) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [2]=>
  int(2)
  [3]=>
  int(3)
  [5]=>
  int(5)
  [6]=>
  int(6)
  [7]=>
  int(7)
}

respondido 05 mar '20, 00:03

aquí hay una solución simple pero comprensible:

$messagesFiltered = [];
foreach ($messages as $message) {
    if (401 != $message) {
        $messagesFiltered[] = $message;
    }
}
$messages = $messagesFiltered;

respondido 06 nov., 20:16

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.