質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.83%

unsetを用いた配列の削除について

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 464

aae_11

score 134

以下のコードなのですが、$item_info_listのキーstatusが「0」だった場合、配列を削除することを想定し、書いたコードなのですが、実行しますと

array(1) { [0]=> array(5) { ["id"]=> int(24) ["name"]=> string(10) "テスト2" ["price"]=> int(200) ["img"]=> string(8) "img/test" ["status"]=> string(1) "0" } }


このようになってしまいます。$item_info_listに含まれている2つの配列のキーstatusはどちらも「0」にも関わらず、何故、一つしか配列が削除できないのでしょうか?

$item_info_list = array(
    0 => array('id' => 33, 'name' => 'テスト', 'price' => 100, 'img' => 'img/test', 'status' => '0'),
    1 => array('id' => 24, 'name' => 'テスト2', 'price' => 200, 'img' => 'img/test', 'status' => '0')

);

foreach($item_info_list as $key=> $value){

  if($value['status'] == 0){
    // var_dump($key);
    // exit();
    unset($item_info_list[$key]);
  }

//   var_dump($item_info_list);

  $item_info_list = array_values($item_info_list);
}
var_dump($item_info_list);
exit();
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+2

用途が分からないので何とも言えませんけど、これくらいの内容だったら新しく配列作ったほうが分かりやすいコードになると思います。

$new_list = [];
foreach($item_info_list as $key=> $value){
  if($value['status'] === '0') continue;
  $new_list[$key] = $value;
}
var_dump($new_list);

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/29 15:57

    よく使うのはメモリの解放。
    大きなデータを変数に持たせるとメモリを沢山使うので、
    適宜解放することで使っていない変数が保持する領域を解除します。

    キャンセル

  • 2019/07/29 16:01

    そうなんですね。となりますと、配列に格納される小さな値を削除したといった場合には、あまり使わない方が良いのでしょうか?

    キャンセル

  • 2019/07/29 16:06

    それももとの配列をどう使いたいかによります。
    基本的にですが、PHPはプログラムが最後まで読まれると自動的にメモリを解放するものなので、総データ量が小さいようであれば「削除するのではなく使わないだけにする」という選択肢もあります。
    余程パフォーマンスを求めるのであれば使う場面がないとは言えませんが、そういう細かいところよりロジックの見直しの方が何倍も有用です。

    キャンセル

checkベストアンサー

+1

配列を削除することを想定し、書いたコード

コードが提示されていません。
普通にfilter処理すればよいと思います

$item_info_list = array(
  0 => array('id' => 33, 'name' => 'テスト', 'price' => 100, 'img' => 'img/test', 'status' => '0'),
  1 => array('id' => 24, 'name' => 'テスト2', 'price' => 200, 'img' => 'img/test', 'status' => '0'),
);

$item_info_list = array_filter($item_info_list,function($x){
  return $x["status"]!=="0";
});
print_r($item_info_list);

参考

削除するときは配列のケツから処理するとよいです

$a=["a","b","c","d","e"];
for($i=0;$i<count($a);$i++){
  if(in_array($a[$i],["b","c","d"])) unset($a[$i]);
  $a = array_values($a);
}
print_r($a);


これをすると"b"を削除したとき後ろのデータがつまってきて、連続データの"c"が
削除されないのでNG

$a=["a","b","c","d","e"];
for($i=count($a)-1;$i>=0;$i--){
  if(in_array($a[$i],["b","c","d"])) unset($a[$i]);
  $a = array_values($a);
}
print_r($a);


後ろから回せばつまっても問題ない

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/29 12:19

    配列の下にコードが隠れています。

    キャンセル

  • 2019/07/29 12:21

    失礼しました。見落としていました

    キャンセル

  • 2019/07/29 14:30

    参考処理を追記しておきました

    キャンセル

  • 2019/07/29 15:41

    ご回答ありがとうございます。
    for文で回した場合、何故、連続した要素が削除できなかったのかが分かりました。
    foreachにしても、 array_values()でキーが振りなおされている為、つまってしまったといった感じだったのですね...

    キャンセル

+1

foreachで配列を回しながら中身を削除したり、($item_info_list = array_values($item_info_list);のように)途中で配列を入れ替えたりと言った操作は、予期しない動作を招きますので、どのように動くのか熟知しているのでなければやってはいけません

条件で配列を振り分けるarray_filter関数を使うのがいいでしょう。

$item_info_list = array(
    0 => array('id' => 33, 'name' => 'テスト', 'price' => 100, 'img' => 'img/test', 'status' => '0'),
    1 => array('id' => 24, 'name' => 'テスト2', 'price' => 200, 'img' => 'img/test', 'status' => '0')

);

$filtered = array_filter($item_info_list, function($item) {
  return $item['status'] !== '0';
});

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/29 12:59 編集

    ご回答ありがとうございます。
    少し、疑問に思ったのですが、「return $item['status'] !== '0';」こちらの部分で$item_info_listは多次元配列にもかかわらず、$item[0]['status']のように指定しなくても良いのは何故なのでしょうか...?

    キャンセル

  • 2019/07/29 13:08

    > $item_info_listは多次元配列なのに、$item[0]['status']のように指定しなくても良いのは何故なのでしょうか...?

    array_filterのコールバックには、要素が1つずつ送られています。

    キャンセル

  • 2019/07/29 13:18

    ご返信ありがとうございます。
    array_filterの仕様のようなものとの解釈で合っていますでしょうか?

    キャンセル

  • 2019/07/29 13:19

    そうですね。

    キャンセル

0

$item_info_list = array_values($item_info_list);

これを消してしまえば動きます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/07/29 15:44

    他の方のご回答から、理解することができたのですが、$array_valuesが原因でキーが振りなおされてしまっていたことが原因のようでした...

    キャンセル

  • 2019/07/29 16:55

    それを言うなら array_values() でしょう。
    ちなみに削除じゃなくて、 foreach() ループの外に出しても正常に動きます。(というか、それが当初の希望の処理なのでしょうが)
    foreach() や array_filter() が反復処理を行うということが理解できていれば良いのですが。

    キャンセル

  • 2019/07/29 17:24

    >array_filter() が反復処理
    この点につきましては、maisumakunさんにご解説頂き、理解することができました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.83%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る