Eliminar matriz de PHP por valor (no clave)
Frecuentes
Visto 1,007 veces
1017
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.
20 Respuestas
1786
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
778
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
142
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
64
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
46
$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
30
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
27
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
17
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
15
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
14
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
8
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
6
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
6
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
4
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
3
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
2
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
2
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
1
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
1
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
1
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 php arrays or haz tu propia pregunta.
@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? - dzona
La misma pregunta : stackoverflow.com/questions/1883421/… - Eric Lavoie
posible duplicado de PHP Eliminar un elemento de una matriz - Alex