Jak usunąć element tablicy w pętli foreach?

127

Chcę przejść przez tablicę z, foreachaby sprawdzić, czy istnieje wartość. Jeśli wartość istnieje, chcę usunąć element, który ją zawiera.

Mam następujący kod:

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

Nie wiem, jak usunąć element po znalezieniu wartości. Jak to usunąć?

Muszę użyć foreachdo tego problemu. Prawdopodobnie istnieją alternatywy foreachi możesz się nimi podzielić.

ajsie
źródło

Odpowiedzi:

220

Jeśli zdobędziesz również klucz, możesz usunąć ten element w następujący sposób:

foreach ($display_related_tags as $key => $tag_name) {
    if($tag_name == $found_tag['name']) {
        unset($display_related_tags[$key]);
    }
}
Gumbo
źródło
3
Dodatkowe informacje na temat optymalizacji przy użyciu $key => &$tag_name stackoverflow.com/a/2008893/922522
Justin
5
Zauważ, że tablice indeksowane z nieustawionymi elementami mogą być reprezentowane jako obiekty zamiast tablic po rozszerzeniu json_encode(). Możesz rozwiązać ten problem za pomocą $display_related_tags = array_values ($display_related_tags);po foreachpętli.
Márton Tamás
Zauważ, że sztuczka polega na dodaniu wartości do pętli foreach ;-)
Mr Washington
5
Zobacz odpowiedź @Neils. Napotkasz nieoczekiwane błędy, szczególnie jeśli pracujesz z Array of stdClasses. Lubisz nieoczekiwane zachowanie? Ja nie.
happy_marmoset
Odpowiedź @happy_marmoset Neils nie pomaga. Fragment $projects = array_filter($projects, function ($project) { return count($project->roles) > 0; });konwertuje wynik na obiekt.
Paritosh
36

Lepszym rozwiązaniem jest skorzystanie z array_filterfunkcji:

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

Jak czytamy w dokumentacji php :

Ponieważ foreach polega na wewnętrznym wskaźniku tablicy w PHP 5, zmiana go w pętli może prowadzić do nieoczekiwanego zachowania.

W PHP 7 foreach nie używa wewnętrznego wskaźnika tablicy.

Neils
źródło
Zauważ, że trzecim parametrem powinien być ARRAY_FILTER_USE_KEY, aby przekazać klucz jako $ e tutaj.
namezero
@namezero OK, dlaczego ma to znaczenie?
AbraCadaver
@AbraCadaver Z dokumentacji ( 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. To powiedziawszy, ponowne przeczytanie odpowiedzi w tym przypadku oczywiście nie miałoby znaczenia, jak twierdzisz.
namezero
WAŻNE Jeśli chcesz zachować tablicę w kolejności uporządkowanej, musisz wywołać display_related_tags = array_values(display_related_tags);po niej.
guyaloni
9
foreach($display_related_tags as $key => $tag_name)
{
    if($tag_name == $found_tag['name'])
        unset($display_related_tags[$key];
}
Steve H.
źródło
3
„unlink” odłącza pliki, nie ma nic wspólnego ze zmiennymi, a dokładniej z tablicami. Może masz na myśli „niestabilny”?
am
6

Zamiast wykonywać pętlę foreach () na tablicy, szybsze byłoby użycie funkcji array_search () do znalezienia odpowiedniego klucza. W przypadku małych tablic wybrałbym foreach dla lepszej czytelności, ale w przypadku większych tablic lub często wykonywanego kodu powinno to być nieco bardziej optymalne:

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

Operator ścisłego porównania! == jest potrzebny, ponieważ array_search () może zwrócić 0 jako indeks zmiennej $ niechciana wartość.

Ponadto powyższy przykład usunie tylko pierwszą wartość $ niechciana wartość, jeśli $ niechciana wartość może wystąpić więcej niż raz w tablicy $, należy użyć array_keys (), aby znaleźć je wszystkie:

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

Sprawdź http://php.net/manual/en/function.array-search.php, aby uzyskać więcej informacji.

PiotrN
źródło
0

jeśli masz scenariusz, w którym musisz usunąć więcej niż jedną wartość z tablicy foreach, w tym przypadku musisz przekazać wartość przez odniesienie dla każdego: Próbuję wyjaśnić ten scenariusz:

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]);

                        }
               }
}

w drugiej pętli chcesz anulować pierwsze wpisy pętli, nie pojawiają się ponownie w iteracji ze względu na wydajność, ani też nie są usuwane z pamięci, ponieważ w pamięci są obecne i pojawią się w iteracjach.

Hassan Ali Shahzad
źródło
0

Są już odpowiedzi, które pokazują, jak rozbrajać. Zamiast powtarzać kod we wszystkich swoich klasach, spraw, aby działały jak poniżej i używaj go w kodzie, gdy jest to wymagane. W logice biznesowej czasami nie chcesz ujawniać niektórych właściwości. Zobacz poniżej jedno wezwanie do usunięcia

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

Zadzwoń jak:

removeKeysFromAssociativeArray($arrValues, $keysToRemove);
Somnath Muluk
źródło
-1

Jak już wspomniano, chciałbyś zrobić foreach z kluczem i wyłączyć go za pomocą klucza - ale pamiętaj, że mutowanie tablicy podczas iteracji jest generalnie złym pomysłem, chociaż nie jestem pewien co do zasad PHP w tym zakresie bezceremonialny.

Ciarán Walsh
źródło
2
Niezależnie od tego, php foreach zostanie wykonany na całej tablicy. Przetestuj usuwanie wartości, która jest następna w iteracji. Będzie iterować po przesunięciu, ale wartość będzie zerowa.
Kevin Peno
Jeśli nie zmutujesz tablicy podczas iteracji, jak w ogóle zmutować tablicę? Może być średnia foreachlub forogólnie konstrukcje zamiast iteracji?
Gherman
Jest to bardziej komentarz do innej odpowiedzi niż odpowiedź sama w sobie.
Sinister Beard