Como você remove um elemento de matriz em um loop foreach?

127

Eu quero percorrer uma matriz com foreachpara verificar se existe um valor. Se o valor existir, desejo excluir o elemento que o contém.

Eu tenho o seguinte código:

foreach($display_related_tags as $tag_name) {
    if($tag_name == $found_tag['name']) {
        // Delete element
    }
}

Não sei como excluir o elemento depois que o valor for encontrado. Como eu o apago?

Eu tenho que usar foreachpara este problema. Provavelmente existem alternativas para foreach, e você pode compartilhá-las.

ajsie
fonte

Respostas:

219

Se você também receber a chave, poderá excluir esse item da seguinte maneira:

foreach ($display_related_tags as $key => $tag_name) {
    if($tag_name == $found_tag['name']) {
        unset($display_related_tags[$key]);
    }
}
quiabo
fonte
3
Algumas informações adicionais sobre otimização usando $key => &$tag_name stackoverflow.com/a/2008893/922522
Justin
5
Observe que matrizes indexadas com itens não definidos podem ser representados como objetos em vez de matrizes após a json_encode(). Você pode resolver isso $display_related_tags = array_values ($display_related_tags);depois do foreachloop.
Márton Tamás
Note-se que é o truque aqui é para adicionar um valor para o loop foreach ;-)
Sr. Washington
5
Por favor, veja a resposta @Neils. Você encontrará bugs inesperados, especialmente se você trabalhar com a Matriz de stdClasses. Você gosta de comportamento inesperado? Eu não.
happy_marmoset
@happy_marmoset A resposta de Neils não está ajudando. Snippet $projects = array_filter($projects, function ($project) { return count($project->roles) > 0; });converte resultado em objeto.
Paritosh 6/10/10
36

Uma solução melhor é usar a array_filterfunção:

$display_related_tags =
    array_filter($display_related_tags, function($e) use($found_tag){
        return $e != $found_tag['name'];
    });

Como a documentação do php lê:

Como o foreach depende do ponteiro interno do array no PHP 5, alterá-lo no loop pode levar a um comportamento inesperado.

No PHP 7, o foreach não usa o ponteiro interno da matriz.

Neils
fonte
Observe que o terceiro parâmetro deve ser ARRAY_FILTER_USE_KEY para passar a chave como $ e aqui.
namezero
@namezero OK, por que isso importa aqui?
AbraCadaver 18/02
@AbraCadaver A partir da documentação ( php.net/manual/en/function.array-filter.php ): ARRAY_FILTER_USE_KEY - pass key as the only argument to callback instead of the value ARRAY_FILTER_USE_BOTH - pass both value and key as arguments to callback instead of the value Default is 0 which will pass value as the only argument to callback instead. Dito isto, ler a resposta novamente neste caso, é claro, não importaria como você afirma.
namezero 23/02
Importante Se você estiver interessado em manter a matriz como matriz ordenada, precisará chamá- display_related_tags = array_values(display_related_tags);la.
guyaloni 4/06
9
foreach($display_related_tags as $key => $tag_name)
{
    if($tag_name == $found_tag['name'])
        unset($display_related_tags[$key];
}
Steve H
fonte
3
'desvincular' desvincula arquivos, não tem nada a ver com variáveis ​​ou, mais especificamente, com matrizes. Talvez você queira dizer "não definido"?
quer
6

Em vez de executar o loop foreach () na matriz, seria mais rápido usar array_search () para encontrar a chave correta. Em matrizes pequenas, eu usaria o foreach para obter melhor legibilidade, mas para matrizes maiores ou código frequentemente executado, isso deve ser um pouco mais ideal:

$result=array_search($unwantedValue,$array,true);
if($result !== false) {
  unset($array[$result]);   
}

O operador de comparação estrita! == é necessário, porque array_search () pode retornar 0 como o índice do $ unwantedValue.

Além disso, o exemplo acima removerá apenas o primeiro valor $ unwantedValue, se o $ unwantedValue puder ocorrer mais de uma vez na matriz $, você deve usar array_keys () para encontrar todos eles:

$result=array_keys($array,$unwantedValue,true)
foreach($result as $key) {
  unset($array[$key]);
}

Verifique http://php.net/manual/en/function.array-search.php para obter mais informações.

PiotrN
fonte
0

se você tiver um cenário no qual precisará remover mais de um valor da matriz foreach, nesse caso, precisará passar o valor por referência para cada um: tento explicar este cenário:

foreach ($manSkuQty as $man_sku => &$man_qty) {

               foreach ($manufacturerSkus as $key1 => $val1) {

  // some processing here and unset first loops entries                     
 //  here dont include again for next iterations
                           if(some condition)
                            unset($manSkuQty[$key1]);

                        }
               }
}

no segundo loop, você deseja desabilitar as primeiras entradas de loop não retornando a iteração para fins de desempenho, ou então desabilitadas da memória também, porque na memória elas apresentam e entrarão em iterações.

Hassan Ali Shahzad
fonte
0

Já existem respostas que estão esclarecendo como desabilitar. Em vez de repetir o código em todas as suas classes, faça as funções abaixo e use-o no código sempre que necessário. Na lógica de negócios, às vezes você não deseja expor algumas propriedades. Veja abaixo uma chamada de linha para remover

public static function removeKeysFromAssociativeArray($associativeArray, $keysToUnset)
{
    if (empty($associativeArray) || empty($keysToUnset))
        return array();

    foreach ($associativeArray as $key => $arr) {
        if (!is_array($arr)) {
            continue;
        }

        foreach ($keysToUnset as $keyToUnset) {
            if (array_key_exists($keyToUnset, $arr)) {
                unset($arr[$keyToUnset]);
            }
        }
        $associativeArray[$key] = $arr;
    }
    return $associativeArray;
}

Ligue como:

removeKeysFromAssociativeArray($arrValues, $keysToRemove);
Somnath Muluk
fonte
-1

Como já foi mencionado, você deseja fazer um foreach com a chave e desmarcar usando a chave - mas observe que a mutação de uma matriz durante a iteração é geralmente uma má ideia, embora eu não tenha certeza das regras do PHP sobre isso. de imediato.

Ciarán Walsh
fonte
2
Um php foreach será executado em toda a matriz, independentemente. Teste a desativação de um valor que é o próximo na iteração. Ele irá iterar no deslocamento, mas o valor será nulo.
22610 Kevin Peno
Se você não modifica uma matriz durante a iteração, como mutá-la? Pode ser média foreachou forconstruções em vez de iteração em geral?
Gherman
Isso é mais um comentário sobre outra resposta do que uma resposta por si só.
Barba Sinistra