Eliminar elemento de matriz por valor

166

Necesito eliminar el elemento de matriz con el valor dado:

if (in_array($id, $items)) {
    $items = array_flip($items);
    unset($items[ $id ]);
    $items = array_flip($items);
}

¿Podría hacerse de manera más corta (más eficiente)?

Marek
fuente
1
Posible duplicado de la matriz PHP eliminada por valor (no clave)
Ben

Respuestas:

423

Se puede lograr con una simple línea.

Teniendo esta matriz:

$arr = array('nice_item', 'remove_me', 'another_liked_item', 'remove_me_also');

Tu puedes hacer:

$arr = array_diff($arr, array('remove_me', 'remove_me_also'));

Y el valor de $arrserá:

array('nice_item', 'another_liked_item')

Espero que ayude a escribir un código hermoso.

Alejandro García Iglesias
fuente
2
No, hace obras con matrices de referencia, la array_difffunción es no destructivo, que devuelve una nueva matriz.
Alejandro García Iglesias
2
@srcspider ¿por qué no? $referenced = array_diff($referenced, $items_to_remove);
Alejandro García Iglesias
1
$ referenciado ahora apunta a una nueva matriz, la matriz que desea cambiar todavía tiene los valores antiguos.
srcspider
2
@srcspider bueno, entonces dime qué está pasando aquí ... codepad.org/11ZhiFP0
Alejandro García Iglesias
1
culpa mía; El truco de alias variable de php siempre me hace
tropezar
37

Estoy agregando una segunda respuesta. Escribí un script de evaluación comparativa rápida para probar varios métodos aquí.

$arr = array(0 => 123456);
for($i = 1; $i < 500000; $i++) {
    $arr[$i] = rand(0,PHP_INT_MAX);
}

shuffle($arr);
$arr2 = $arr;
$arr3 = $arr;

/** 
 * Method 1 - array_search()
 */
$start = microtime(true);
while(($key = array_search(123456,$arr)) !== false) {
    unset($arr[$key]);
}
echo count($arr). ' left, in '.(microtime(true) - $start).' seconds<BR>';

/** 
 * Method 2 - basic loop
 */
$start = microtime(true);
foreach($arr2 as $k => $v) {
    if ($v == 123456) {
        unset($arr2[$k]);
    }
}
echo count($arr2). 'left, in '.(microtime(true) - $start).' seconds<BR>';

/** 
 * Method 3 - array_keys() with search parameter
 */
$start = microtime(true);
$keys = array_keys($arr3,123456);
foreach($keys as $k) {
    unset($arr3[$k]);
}
echo count($arr3). 'left, in '.(microtime(true) - $start).' seconds<BR>';

El tercer método, array_keys()con el parámetro de búsqueda opcional especificado, parece ser, con mucho, el mejor método. Ejemplo de salida:

499999 left, in 0.090957164764404 seconds
499999left, in 0.43156313896179 seconds
499999left, in 0.028877019882202 seconds

A juzgar por esto, la solución que usaría entonces sería:

$keysToRemove = array_keys($items,$id);
foreach($keysToRemove as $k) {
    unset($items[$k]);
}
zombat
fuente
Creo que array_search es un código mucho más legible que usar el método array_diff. Votación a favor
kendepelchin
@zombat Me pregunto si el orden tiene algo que ver con los resultados. Es posible que shuffle ponga el valor que estamos buscando más cerca del frente o del final. Aparte de eso ... +1
General Redneck
31

Qué tal si:

if (($key = array_search($id, $items)) !== false) unset($items[$key]);

o para múltiples valores:

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

Esto también evitaría la pérdida de claves, que es un efecto secundario de array_flip().

zombat
fuente
1
no funcionará si $ id es el primer elemento de la matriz, mejor así: if (($ key = array_search ($ id, $ items))! == false) unset ($ items [$ key]);
Marek
15

para eliminar $rm_valde$arr

unset($arr[array_search($rm_val, $arr)]);
Toma
fuente
8

Sería la solución más poderosa array_filter, que le permite definir su propia función de filtrado.

Pero algunos podrían decir que es un poco exagerado, en su situación ...
Un simple foreachciclo para recorrer la matriz y eliminar el elemento que no desea debería ser suficiente.

Algo como esto, en su caso, probablemente debería hacer el truco:

foreach ($items as $key => $value) {
    if ($value == $id) {
        unset($items[$key]);
        // If you know you only have one line to remove, you can decomment the next line, to stop looping
        //break;
    }
}
Pascal MARTIN
fuente
6

Prueba array_search ()

Salvaje
fuente
3
Acabo de leer la documentación, y recomienda usar array_keys () para encontrar todas las claves asociadas a un valor.
Savageman
@Savageman - De acuerdo. Ejecuté un punto de referencia rápido y array_keys()parece funcionar mejor que array_search()para esta tarea.
zombat
6

Sus soluciones solo funcionan si tiene valores únicos en su matriz

Ver:

<?php
$trans = array("a" => 1, "b" => 1, "c" => 2);
$trans = array_flip($trans);
print_r($trans);
?>

Una mejor manera sería desarmar con array_search , en un bucle si fuera necesario.

Dutow
fuente
tienes razón, pero en este caso particular estoy bastante seguro de que los valores son únicos :)
Marek
5

sin voltear:

<?php
foreach ($items as $key => $value) {
    if ($id === $value) {
        unset($items[$key]);
    }
}
Erenon
fuente
5
function deleteValyeFromArray($array,$value)
{
   foreach($array as $key=>$val)
   {
      if($val == $value)
      {
         unset($array[$key]);
      }
   }
   return $array;
}
Suman Biswas
fuente
4

Puede usar la función array_splice para esta operación Ref: array_splice

array_splice($array, array_search(58, $array ), 1);
Tejas Soni
fuente