PHP配列はキーではなく値で削除します


886

次のようなPHP配列があります。

$messages = [312, 401, 1599, 3, ...];

値を含む要素$del_val(たとえば$del_val=401)を削除したいのですが、そのキーがわかりません。これは役立つかもしれません:各値は一度だけ存在できます。

このタスクを実行する最も簡単な機能を探しています。


1
@Adam Strudwickしかし、この配列で多数の削除がある場合、一度繰り返して、キーを値と同じにする方が良いでしょうか?
dzona 2013年


回答:


1566

array_search()およびを使用してunset、次のことを試してください。

if (($key = array_search($del_val, $messages)) !== false) {
    unset($messages[$key]);
}

array_search()見つかった要素のキーを返します。これを使用して、を使用して元の配列からその要素を削除できますunset()FALSE失敗すると戻りますが、成功するとfalse-y値を返す可能性があります(0たとえば、キーがその可能性があります)。そのため、厳密な比較!==演算子が使用されます。

このif()ステートメントはarray_search()、値が返されたかどうかをチェックし、返された場合にのみアクションを実行します。


14
$ messages = array_diff($ messages、array($ del_val))も機能しますか?パフォーマンスは良くなりますか?
Adam Strudwick、2011

9
@Adamなぜそれをテストしないのですか?私の気持ちはつまりarray_diff()、それはだと遅くなり2つの比較単にを検索ない、アレイの1のようにarray_search()
Bojangles 2011

22
これは有効ですが、そのようなステートメントで値を割り当てることは避けてください。トラブルに巻き込まれるだけです。
adlawson 2011

17
何場合は$keyありますか0
エヴァン、2011

16
検索する値にキー0またはその他の誤った値がある場合、値の設定が解除されず、コードは機能しません。あなたはテストする必要があります$key === false。(編集-あなたはそれを得た)
エヴァン

674

まあ、配列から要素を削除することは、基本的に1つの要素との差を設定するだけです。

array_diff( [312, 401, 15, 401, 3], [401] ) // removing 401 returns [312, 15, 3]

それはうまく一般化し、必要に応じて、好きなだけ多くの要素を同時に削除できます。

免責事項:私の解決策は、変化する受け入れられた回答とは対照的に、古いものをそのまま維持しながら、配列の新しいコピーを生成することに注意してください。必要なものを選択してください。


32
これは文字列に変換できるオブジェクトに対してのみ機能します
nischayn22

7
と言って「解析エラー」が発生して[$element]いるarray($element)ようです。代わりに使用しました。大したことはありませんが、同様の問題を抱えている人が一人ではないことを知って
ほしい

8
もちろん、私はPHP 5.4が主に古い表記を落とすことを想定しています。発言ありがとうございます。
Rok Kralj 2013

22
なんらかの理由で、予想どおりではなく、等価条件としてarray_diff使用さ(string) $elem1 === (string) $elem2れていることに注意し$elem1 === $elem2てください。@ nischayn22によって指摘された問題は、この結果です。任意の要素(オブジェクトである可能性があります)の配列に対して機能するユーティリティ関数として何かを使用したい場合は、この理由からBojangleの答えの方が良いでしょう。
Mark Amery

4
また、このメソッドは各引数に対して内部的にソートをarray_diff()実行し、ランタイムをO(n)からO(n lg n)までナッジします。
ジャック

115

興味深い方法の1つは、次のものを使用することarray_keys()です。

foreach (array_keys($messages, 401, true) as $key) {
    unset($messages[$key]);
}

このarray_keys()関数は、特定の値のキーのみを返すために2つの追加のパラメーターを受け取り、厳密なチェックが必要かどうか(つまり、比較に===を使用)を使用します。

これにより、同じ値を持つ複数の配列項目を削除することもできます(例:)[1, 2, 3, 3, 4]


3
@blasteralfredΨ線形検索はO(n);です。なぜそれが問題だと思うのか、よくわかりません。
ジャック

1
はい、これは複数の配列項目/キーを選択するのに効果的です。
沖エリーリナルディ2014

3
これは、すべての一意の値が含まれていない可能性がある配列に最適です。
デロコリン2014年

問題は、キーのインデックスが分類されたままになっていることです:[0]-a、[2]-b([1]はなくなっていますが、配列にはまだありません)
Rodniko

3
@Rodnikoその場合、あなたも必要array_values()になります。残りのキーは、その技術的には「未ソート」ではありません、しかし同じ順序にまだある
ジャック

55

配列にその値を持つ要素が1つだけ含まれることが明確にわかっている場合は、

$key = array_search($del_val, $array);
if (false !== $key) {
    unset($array[$key]);
}

ただし、値が配列で複数回出現する可能性がある場合は、これを行うことができます

$array = array_filter($array, function($e) use ($del_val) {
    return ($e !== $del_val);
});

注: 2番目のオプションは、のみでPHP5.3 +のために働くクロージャ


41
$fields = array_flip($fields);
unset($fields['myvalue']);
$fields = array_flip($fields);

11
これは、削除しようとしている値以外の重複する値が配列に含まれていない場合にのみ機能します。
jberculo

2
@jberculoそして時にはそれがまさにあなたが必要とするものであり、いくつかのケースではそれは私がその上でユニークな配列を行うことを節約します
DarkMukke

多分、しかし、私は基本的に使用され、他の何かのために意図された関数の単なる幸運な副作用ではなく、それを行うために特別に設計された関数を使用します。また、コードの透過性が低下します。
jberculo 2014年

このメッセージは、「各値は一度しか存在できません」と述べており、これは機能するはずです。ポスターがsmae変数名を使用し、少し説明を加えていたら良かったでしょう
Raatje

2
明らかに、これは選択したソリューションと比較して最速です。私は小さなベンチマークを行いました。
2017年

28

次のコードを見てください:

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

できるよ:

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

そして、それはあなたにこの配列を取得します:

array('nice_item', 'another_liked_item')

1
連想配列の場合は、array_diff_assoc()を使用する必要があります
theCodeMachine

5
これはこの回答とどう違うのですか?
random_user_name 2016

26

最良の方法は array_splice

array_splice($array, array_search(58, $array ), 1);

最高の理由はhttp://www.programmerinterview.com/index.php/php-questions/how-to-delete-an-element-from-an-array-in-php/にあります。


4
これは、連想配列や、キーにギャップがある配列では機能しません[1, 2, 4 => 3]
ジャック

申し訳ありませんが、これでうまくいきます。私がリンクを提供した記事を読んでください
Airy

4
それはしません。上記のコメントの配列を検討してください。コードを使用して値を削除する3と、配列は次のようになり[1, 2, 3]ます。つまり、値は削除されませんでした。明確にするために、これがすべてのシナリオで失敗すると言っているのではなく、これだけです。
ジャック・

1
array_spliceが最善の方法で、unsetは削除後に配列インデックスを調整しません
Raaghu

21

または単に、手動の方法:

foreach ($array as $key => $value){
    if ($value == $target_value) {
        unset($array[$key]);
    }
}

アレイを完全に制御できるため、これが最も安全です。


1
array_splice()代わりにunset()を使用すると、配列のインデックスも並べ替えられます。これは、この場合に適しています。
ダニエレオーランド

20

次のコードにより、反復的な値が$ messagesから削除されます。

$messages = array_diff($messages, array(401));


3
賛成票。それはすでに他の答えの中にありましたが、あなたがそうであるように、あなたはそれを単純に保つことによってそれを最もよく言います。答えは単に「array_diff」です
ghbarratt

1
シンプルに見えますが、複雑さをO(n)からO(n lg n)に変更します。したがって、実際にはもっと複雑です;)
Krzysztof Przygoda '20

20

PHPを使用している場合5.3+は、次の1行のコードがあります。

$array = array_filter($array, function ($i) use ($value) { return $i !== $value; }); 

本気ですか?その閉鎖はへのアクセス権を持っていない$valueので、本当にそれはあなたがアクセスできるように、ミニクラスに入れなければならず、$value....クロージャ内
random_user_name

@cale_b、例を更新しました。また、ref:php.net/manual/en/functions.anonymous.php
David Lin

3
この「1行のコード」を呼び出す場合は、コードベース全体を1行で記述することもできます
Milan Simek

16
function array_remove_by_value($array, $value)
{
    return array_values(array_diff($array, array($value)));
}

$array = array(312, 401, 1599, 3);

$newarray = array_remove_by_value($array, 401);

print_r($newarray);

出力

Array ( [0] => 312 [1] => 1599 [2] => 3 )


2
このソリューションには複数の関数呼び出しが含まれるため、これが高速かどうかはわかりません。
Julian Paolo Dayag 2016年

13

できるよ:

unset($messages[array_flip($messages)['401']]);

説明401配列を反転した後、キーを持つ要素を削除してください。


状態を保存したい場合は、非常に注意する必要があります。将来のすべてのコードには、キーの代わりに値が必要になるためです。
saadlulu

1
@saadlulu $ messages配列は反転されません。array_flip()は元の配列に影響を与えないため、前の行を適用した後の結果の配列は、不要な結果が削除されることを除いて同じになります。
Qurashi

2
これが正しいかどうかはわかりませんが、値がの要素が複数ある場合は401どうなりますか?
Zippp

これでもキーは保持されます。
SzabolcsPáll

8

複数の値を削除するには、これを試してください:

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

6

underscore.JS _.rejectのロジックを借用し、2つの関数を作成しました(人々は関数を好む!!)

array_reject_value:この関数は、指定された値を単に拒否します(PHP4、5、7でも機能します)

function array_reject_value(array &$arrayToFilter, $deleteValue) {
    $filteredArray = array();

    foreach ($arrayToFilter as $key => $value) {
        if ($value !== $deleteValue) {
            $filteredArray[] = $value;
        }
    }

    return $filteredArray;
}

array_reject:この関数は単に呼び出し可能なメソッドを拒否しています(PHP> = 5.3で機能)

function array_reject(array &$arrayToFilter, callable $rejectCallback) {

    $filteredArray = array();

    foreach ($arrayToFilter as $key => $value) {
        if (!$rejectCallback($value, $key)) {
            $filteredArray[] = $value;
        }
    }

    return $filteredArray;
}

したがって、現在の例では、上記の関数を次のように使用できます。

$messages = [312, 401, 1599, 3, 6];
$messages = array_reject_value($messages, 401);

またはさらに良い:(これにより、array_filterのように使用するためのより良い構文が得られます)

$messages = [312, 401, 1599, 3, 6];
$messages = array_reject($messages, function ($value) {
    return $value === 401;
});

上記は、401以上のすべての値を削除したい場合など、より複雑なものに使用できます。

$messages = [312, 401, 1599, 3, 6];
$greaterOrEqualThan = 401;
$messages = array_reject($messages, function ($value) use $greaterOrEqualThan {
    return $value >= $greaterOrEqualThan;
});

1
これは再発明フィルターではないですか?php.net/manual/en/function.array-filter.php
Richard Duerr

はい、そうです。私がすでに投稿で言っているように、「またはさらに良い:(これは、array_filterのように使用するためのより良い構文を与えるので)」。場合によっては、本当にアンダースコアとして関数を拒否する必要があり、それは実際にはフィルターのちょうど反対です(そして、できるだけ少ないコードで取得する必要があります)。これが関数が行っていることです。これは値を拒否する簡単な方法です。
John Skoumbourdis 16年

6
$array = array("apple", "banana",'mango');
$array = array_filter($array, function($v) { return $v != "apple"; });

これを試してください、これは値によって要素を削除するための最良かつ最速の方法です


5

@Bojanglesの回答が役に立ちました。ありがとうございました。

私の場合、配列は連想的であるかどうかに関係なく、次の関数を追加しました

function test($value, $tab) {

 if(($key = array_search($value, $tab)) !== false) {
    unset($tab[$key]); return true;

 } else if (array_key_exists($value, $tab)){
        unset($tab[$value]); return true;

 } else {
    return false; // the $value is not in the array $tab
 }

}

よろしく



4

受け入れられた回答は配列を連想配列に変換するので、受け入れられた回答で非連想配列として保持したい場合は、それも使用する必要がありarray_valuesます。

if(($key = array_search($del_val, $messages)) !== false) {
    unset($messages[$key]);
    $arr = array_values($messages);
}

参考はこちら


4

要件によると、配列に一意の値を保持することにのみ関心がある場合は、各値は一度だけ存在することができます」ので、array_unique()探している可能性があります。

入力:

$input = array(4, "4", "3", 4, 3, "3");
$result = array_unique($input);
var_dump($result);

結果:

array(2) {
  [0] => int(4)
  [2] => string(1) "3"
}

4

削除する値が配列内にある場合、または配列内にある可能性がある場合。array_diff関数を使用します。このようなものに最適に動作するようです。

array_diff

$arrayWithValuesRemoved = array_diff($arrayOfData, $arrayOfValuesToRemove);

1
これはこの回答とどう違うのですか?
random_user_name 2016

4

これはまったく効率的ではありませんが、シンプルで直感的で読みやすいことを知っています。
したがって、誰かがより多くの値、またはより具体的な条件で動作するように拡張できるそれほど豪華ではないソリューションを探している場合、ここに簡単なコードを示します。

$result = array();
$del_value = 401;
//$del_values = array(... all the values you don`t wont);

foreach($arr as $key =>$value){
    if ($value !== $del_value){
        $result[$key] = $value;
    }

    //if(!in_array($value, $del_values)){
    //    $result[$key] = $value;
    //}

    //if($this->validete($value)){
    //      $result[$key] = $value;
    //}
}

return $result


3

そのキーがわからない場合、それは重要ではないことを意味します。

値をキーとして配置することもできます。つまり、すぐに値を見つけることができます。すべての要素で何度も検索を使用するよりも優れています。

$messages=array();   
$messages[312] = 312;    
$messages[401] = 401;   
$messages[1599] = 1599;   
$messages[3] = 3;    

unset($messages[3]); // no search needed

文字列に変換できるオブジェクトに対してのみ機能します。
エミールベルジェロン2017

2

or演算子を使用したワンライナー:

($key = array_search($del_val, $messages)) !== false or unset($messages[$key]);

2

あなたはこのURLを参照することができます:機能について

array-diff-key()

<?php
$array1 = array('blue'  => 1, 'red'  => 2, 'green'  => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan'   => 8);

var_dump(array_diff_key($array1, $array2));
?>

次に、出力は、

array(2) {
  ["red"]=>
  int(2)
  ["purple"]=>
  int(4)
}


1

最も簡単な方法は、関数をforeachループで使用することだと思います。

//This functions deletes the elements of an array $original that are equivalent to the value $del_val
//The function works by reference, which means that the actual array used as parameter will be modified.

function delete_value(&$original, $del_val)
{
    //make a copy of the original, to avoid problems of modifying an array that is being currently iterated through
    $copy = $original;
    foreach ($original as $key => $value)
    {
        //for each value evaluate if it is equivalent to the one to be deleted, and if it is capture its key name.
        if($del_val === $value) $del_key[] = $key;
    };
    //If there was a value found, delete all its instances
    if($del_key !== null)
    {
        foreach ($del_key as $dk_i)
        {
            unset($original[$dk_i]);
        };
        //optional reordering of the keys. WARNING: only use it with arrays with numeric indexes!
        /*
        $copy = $original;
        $original = array();
        foreach ($copy as $value) {
            $original[] = $value;
        };
        */
        //the value was found and deleted
        return true;
    };
    //The value was not found, nothing was deleted
    return false;
};

$original = array(0,1,2,3,4,5,6,7,4);
$del_val = 4;
var_dump($original);
delete_value($original, $del_val);
var_dump($original);

出力は次のようになります。

array(9) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [2]=>
  int(2)
  [3]=>
  int(3)
  [4]=>
  int(4)
  [5]=>
  int(5)
  [6]=>
  int(6)
  [7]=>
  int(7)
  [8]=>
  int(4)
}
array(7) {
  [0]=>
  int(0)
  [1]=>
  int(1)
  [2]=>
  int(2)
  [3]=>
  int(3)
  [5]=>
  int(5)
  [6]=>
  int(6)
  [7]=>
  int(7)
}

1

PHP 7.4でアロー関数を使用する場合:

$messages = array_filter($messages, fn ($m) => $m != $del_val);

非連想配列に保つには、次のようにラップしarray_values()ます。

$messages = array_values(array_filter($messages, fn ($m) => $m != $del_val));
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.