Suppression d'un élément de tableau par valeur

166

J'ai besoin de supprimer l'élément de tableau avec une valeur donnée:

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

Cela pourrait-il être fait de manière plus courte (plus efficace)?

Marek
la source

Réponses:

423

Cela peut être accompli avec une simple doublure.

Avoir ce tableau:

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

Tu peux faire:

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

Et la valeur de $arrsera:

array('nice_item', 'another_liked_item')

J'espère que cela aidera à écrire un beau code.

Alejandro García Iglesias
la source
2
Non, il ne fonctionne avec des tableaux référencés, la array_difffonction est non destructive, elle retourne un nouveau tableau.
Alejandro García Iglesias
2
@srcspider pourquoi pas? $referenced = array_diff($referenced, $items_to_remove);
Alejandro García Iglesias
1
$ referenced pointe maintenant vers un nouveau tableau, le tableau que vous vouliez changer a toujours les anciennes valeurs.
srcspider
2
@srcspider eh bien, dites-moi ce qui se passe ici alors ... codepad.org/11ZhiFP0
Alejandro García Iglesias
1
ma faute; Le gimmick d'aliasing variable de php me fait toujours
trébucher
37

J'ajoute une deuxième réponse. J'ai écrit un script d'analyse comparative rapide pour essayer différentes méthodes ici.

$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>';

La troisième méthode, array_keys()avec le paramètre de recherche facultatif spécifié, semble être de loin la meilleure méthode. Exemple de sortie:

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

À en juger par cela, la solution que j'utiliserais alors serait:

$keysToRemove = array_keys($items,$id);
foreach($keysToRemove as $k) {
    unset($items[$k]);
}
zombat
la source
Je pense que array_search est un code beaucoup plus lisible que d'utiliser la méthode array_diff. Upvote
kendepelchin
@zombat Je me demande si l'ordre a quelque chose à voir avec les résultats. Il est possible que la lecture aléatoire place la valeur recherchée plus près du front ou de la fin. Autre que ça ... +1
General Redneck
31

Que diriez-vous:

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

ou pour plusieurs valeurs:

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

Cela éviterait également la perte de clés, ce qui est un effet secondaire de array_flip().

zombat
la source
1
ne fonctionnera pas si $ id est le premier élément du tableau, mieux de cette façon: if (($ key = array_search ($ id, $ items))! == false) unset ($ items [$ key]);
Marek
15

supprimer $rm_valde$arr

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

La solution la plus puissante serait d'utiliser array_filter, qui vous permet de définir votre propre fonction de filtrage.

Mais certains pourraient dire que c'est un peu exagéré, dans votre situation ...
Une simple foreachboucle pour parcourir le tableau et supprimer l'élément que vous ne voulez pas devrait suffire.

Quelque chose comme ça, dans votre cas, devrait probablement faire l'affaire:

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
la source
6

Essayez array_search ()

Savageman
la source
3
Je viens de lire la documentation, et il est recommandé d'utiliser array_keys () pour trouver toutes les clés associées à une valeur.
Savageman
@Savageman - D'accord. J'ai effectué un test rapide et array_keys()semble mieux performer que array_search()pour cette tâche.
zombat
6

Vos solutions ne fonctionnent que si vous avez des valeurs uniques dans votre tableau

Voir:

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

Un meilleur moyen serait de ne pas être défini avec array_search , dans une boucle si nécessaire.

Dutow
la source
vous avez raison, mais dans ce cas particulier, je suis presque sûr que les valeurs sont uniques :)
Marek
5

sans flip:

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

Vous pouvez utiliser la fonction array_splice pour cette opération Ref: array_splice

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