foreachループ内の配列からオブジェクトを削除する方法


140

オブジェクトの配列を反復処理し、その 'id'プロパティに基づいてオブジェクトの1つを削除したいのですが、コードが機能しません。

foreach($array as $element) {
    foreach($element as $key => $value) {
        if($key == 'id' && $value == 'searched_value'){
            //delete this particular object from the $array
            unset($element);//this doesn't work
            unset($array,$element);//neither does this
        } 
    }
}

助言がありますか。ありがとう。


2
可能性のある複製foreachループで配列要素
7hi4g0 2014年

回答:


233
foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        if($valueKey == 'id' && $value == 'searched_value'){
            //delete this particular object from the $array
            unset($array[$elementKey]);
        } 
    }
}

62
同じ配列のforeachループ内で配列の要素を削除しても安全ですか?
Olivier Pons 2012

25
@Oliver:通常、予期しない動作が発生しますが、phpのforeachで安全に実行できます。テストのためにここに読んでください:php.net/manual/en/control-structures.foreach.php#88578
pangon

1
@Paritoshあなたがこれをずっと前に投稿したことは知っていますが、それはPHPが連想配列を使用しているためです。つまり、削除されたインデックスがあり、オブジェクトとしてJSONにエンコードされます。連想配列は「辞書」であるため、理にかなっています。一緒に来る人を助けるかもしれません。
ライアンオドネル

1
あなたは本当にそれぞれの秒を行う必要がありますか?オブジェクトの必要な 'id'プロパティをクエリできないのですか?他のすべての小道具をチェックする理由。
htafoya

3
@htafoyaいいえ、私はif(isset($element['id']) && $element['id'] == 'searched_value') { unset($array[$elementKey]); }彼のコードをコピーして修正したところ、彼にunset適切な方法を示すことができたと思います。
prodigitalson 2017

2

unsetの構文が無効であるようです。インデックスを再作成しないと、将来問題が発生する可能性があります。参照: PHP配列のセクション

正しい構文は上記のとおりです。また、インデックスを再作成するための配列値を覚えておいてください。これにより、以前に削除したものにインデックスを付けることはありません。


2

foreach値の参照を使用することもできます。

foreach($array as $elementKey => &$element) {
    // $element is the same than &$array[$elementKey]
    if (isset($element['id']) and $element['id'] == 'searched_value') {
        unset($element);
    }
}

9
$ element(foreachの内外で使用)は、配列内の各要素への参照です。unset($ element)は参照を破壊するだけで、参照されている要素を配列から破棄しません。
ニコラス

3
@Dev_NIX $element = nullは機能せず、長さは$array同じで、nullが含まれるだけです
Nico Westerdale

1

これでうまくいくはずです。

reset($array);
while (list($elementKey, $element) = each($array)) {
    while (list($key, $value2) = each($element)) {
        if($key == 'id' && $value == 'searched_value') {
            unset($array[$elementKey]);
        }
    }
}

1

主な答えには注意してください。

[['id'=>1,'cat'=>'vip']
,['id'=>2,'cat'=>'vip']
,['id'=>3,'cat'=>'normal']

そして関数を呼び出す

foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        if($valueKey == 'cat' && $value == 'vip'){
            //delete this particular object from the $array
            unset($array[$elementKey]);
        } 
    }
}

戻る

[2=>['id'=>3,'cat'=>'normal']

の代わりに

[0=>['id'=>3,'cat'=>'normal']

これは、unsetが配列のインデックスを再作成しないためです。

インデックスを再作成します。(必要な場合)

$result=[];
foreach($array as $elementKey => $element) {
    foreach($element as $valueKey => $value) {
        $found=false;
        if($valueKey === 'cat' && $value === 'vip'){
            $found=true;
            $break;
        } 
        if(!$found) {
           $result[]=$element;
        }
    }
}

0

私はあまりPHPプログラマではありませんが、C#では、反復処理中に配列を変更することはできません。foreachループを使用して要素のインデックスまたは削除する要素を特定し、ループの後で要素を削除することをお勧めします。


14
ほとんどの言語では悪い習慣ですが、PHPの配列は基本的に連想配列であり、順番に繰り返すことができます。以前の要素を削除しても、その後の要素のキーは変更されません。
Ignacio Vazquez-Abrams、

22
実際には、foreachが内部で使用する配列は元の配列のコピーであるため、許可されます。そうすれば、元の配列を変更することは完全に安全です。
フアン

68
実際には、phpはすべての地獄のように愚かなので、それは許可されています。
エリックG
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.