Removendo item de matriz por valor


166

Preciso remover o item da matriz com um determinado valor:

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

Isso poderia ser feito de maneira mais curta (mais eficiente)?


1
Ben

Respostas:


423

Isso pode ser conseguido com uma linha simples.

Tendo esta matriz:

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

Você pode fazer:

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

E o valor de $arrserá:

array('nice_item', 'another_liked_item')

Espero que ajude a escrever um código bonito.


2
Não, faz trabalhos com matrizes de referência, a array_difffunção é não-destrutivo, ele retorna uma nova matriz.
Alejandro García Iglesias

2
@srcspider porque não? $referenced = array_diff($referenced, $items_to_remove);
Alejandro García Iglesias

1
$ referenced agora está apontando para uma nova matriz, a matriz que você deseja alterar ainda possui os valores antigos.
Srcpider

2
@srcspider bem, você me diz o que está acontecendo aqui, então ... codepad.org/11ZhiFP0
Alejandro García Iglesias

1
foi mal; . gimmick aliasing variável de php sempre me tropeça>>
srcspider

37

Estou adicionando uma segunda resposta. Eu escrevi um script rápido de benchmarking para tentar vários métodos aqui.

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

O terceiro método, array_keys()com o parâmetro de pesquisa opcional especificado, parece ser de longe o melhor método. Exemplo de saída:

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

A julgar por isso, a solução que eu usaria então seria:

$keysToRemove = array_keys($items,$id);
foreach($keysToRemove as $k) {
    unset($items[$k]);
}

Eu acho que array_search é um código muito mais legível do que usar o método array_diff. Upvote
kendepelchin

@ zombat Gostaria de saber se a ordem tem algo a ver com os resultados. É possível que o shuffle coloque o valor que estamos procurando mais perto da frente ou do final. Fora isso ... +1
General Redneck

31

E se:

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

ou para vários valores:

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

Isso impediria a perda de chave também, o que é um efeito colateral do array_flip().


1
não funcionará se $ id for o primeiro elemento da matriz, melhor assim: if (($ key = array_search ($ id, $ items))! == false) unset ($ items [$ key]);
Marek

15

remover $rm_valde$arr

unset($arr[array_search($rm_val, $arr)]);

8

A solução mais poderosa seria usar array_filter, o que permite definir sua própria função de filtragem.

Mas alguns podem dizer que é um pouco exagerado, na sua situação ...
Um foreachloop simples para percorrer a matriz e remover o item que você não deseja deve ser suficiente.

Algo assim, no seu caso, provavelmente deve fazer o truque:

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;
    }
}

6

3
Acabei de ler a documentação e é recomendável usar array_keys () para encontrar todas as chaves associadas a um valor.
Savageman

@Savageman - De acordo. Fiz um benchmark rápido e array_keys()parece ter um desempenho melhor do que array_search()nesta tarefa.
Zombat

6

Suas soluções só funcionam se você tiver valores exclusivos em sua matriz

Vejo:

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

Uma maneira melhor seria desconfigurar com array_search , em um loop, se necessário.


você está certo, mas neste caso particular, eu tenho certeza de que os valores são únicos :)
Marek

5

sem flip:

<?php
foreach ($items as $key => $value) {
    if ($id === $value) {
        unset($items[$key]);
    }
}

5
function deleteValyeFromArray($array,$value)
{
   foreach($array as $key=>$val)
   {
      if($val == $value)
      {
         unset($array[$key]);
      }
   }
   return $array;
}

4

Você pode usar a função array_splice para esta operação Ref: array_splice

array_splice($array, array_search(58, $array ), 1);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.