値による配列項目の削除


166

与えられた値を持つ配列項目を削除する必要があります:

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

それはより短い(より効率的な)方法で行うことができますか?


回答:


423

シンプルなワンライナーで実現できます。

この配列を持つ:

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

できるよ:

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

の値は$arr次のとおりです。

array('nice_item', 'another_liked_item')

美しいコードを書くのに役立つことを願っています。


2
いいえ、それはない参照配列と作品を、array_diff関数は新しい配列を返し、非破壊です。
アレハンドロガルシアイグレシアス

2
@srcspiderなんで?$referenced = array_diff($referenced, $items_to_remove);
アレハンドロガルシアイグレシアス

1
$ referencedは新しい配列を指しているので、変更したい配列にはまだ古い値が残っています。
srcspider 2013

2
@srcspiderよく、ここで何が起こっているのか教えてください... codepad.org/11ZhiFP0
AlejandroGarcíaIglesias

1
私の悪い; phpの変数エイリアシングギミックは常に私を
つまずき

37

2つ目の答えを追加します。ここでさまざまな方法を試すための簡単なベンチマークスクリプトを作成しました。

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

array_keys()オプションの検索パラメーターを指定した3番目の方法は、群を抜いて最良の方法のようです。出力例:

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

これを判断すると、私が使用するソリューションは次のようになります。

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

array_searchは、array_diffメソッドを使用するよりもはるかに読みやすいコードだと思います。賛成票
ケンデペルチン

@zombat注文が結果と関係があるのか​​しら。シャッフルによって、検索している値が前または後のどちらかに置かれる可能性があります。それ以外は... +1
レッドネック将軍2016年

31

どうですか:

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

または複数の値の場合:

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

これにより、の副作用であるキーの損失も防ぐことができますarray_flip()


1
$ idが最初の配列要素の場合は機能しません。この方法の方が適しています。if(($ key = array_search($ id、$ items))!== false)unset($ items [$ key]);
Marek、

15

から削除$rm_valする$arr

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

8

最も強力なソリューションはを使用array_filterすることです。これにより、独自のフィルタリング関数を定義できます。

しかし、あなたの状況では、それは少しやり過ぎだと言う人もいます... 配列を通過し、不要
foreach項目を削除する単純なループで十分です。

あなたの場合、このような何かがおそらくトリックをするはずです:

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

array_search()を試してください


3
私はドキュメントを読んだだけで、array_keys()を使用して値に関連付けられているすべてのキーを見つけることをお勧めします。
サベージマン2009

@サベージマン-そうですね。私は簡単なベンチマークarray_keys()を実行しarray_search()、このタスクよりもパフォーマンスが良いようです。
zombat 2009

6

ソリューションは、配列に一意の値がある場合にのみ機能します

見る:

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

より良い方法は、必要に応じてループでarray_searchを使用して設定を解除することです。


あなたは正しいですが、この特定のケースでは、値が一意であると確信しています:)
Marek

5

フリップなし:

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.