- ベストアンサー
【PHP】 重複した値を取り除く処理
【log.txt の中身】 1,スイカ 2,メロン 3,メロン 4,ミカン 5,スイカ 6,ミカン 次の【file01.php のソース】まではやってみましたが… 【file01.php のソース】 $log = file("log.txt"); for($i=0;$i<sizeof($log);$i++){ list($log1,$log2) = explode( "," , $log[$i]); print "$log2<br>\n"; } …この様にすると次の【出力結果】の様にブラウザーに表示されてしまいます。 【出力結果】 スイカ メロン メロン ミカン スイカ ミカン 次の【出力結果】の様に、重複した値だけを取り除きブラウザーに表示させたいのですが、どうしたら良いのでしょうか?教えて下さい。 【出力結果】 スイカ メロン ミカン
- みんなの回答 (4)
- 専門家の回答
質問者が選んだベストアンサー
$log = file("log.txt"); for($i=0;$i<sizeof($log);$i++){ list($log1,$log2) = explode( "," , $log[$i]); $Data[$log2] = $log1; } var_dump($Data); foreach((array)$Data as $key=>$value) echo $key; ソースファイルをそのまま実行してみてください。 >どのように配列を作ってよいのか分りません。汗 $Data[$log2] = $log1; ↑これが$Dataという配列を作っています。 $Data[$log2] というのは、 log.txtの中身を一列読んで、 $log1= 1; $log2 = "スイカ"; $Data["スイカ"] =1; そしてまたlog.txtの中身を一列読んで、 $log1= 2; $log2 = "メロン"; $Data["メロン"] =2; そしてまたlog.txtの中身を一列読んで、 $log1= 3; $log2 = "メロン"; $Data["メロン"] =3; ・・・ というループを行数分繰り返します。 だから、質問者のlog.txtの場合で、このループを終了したときには $Data["スイカ"] = 5; $Data["メロン"] = 3; $Data["ミカン"] = 4; となります。 >$Data[$log2]の変数は、どこを意味しているのでしょうか? どこで上書きされるのでしょうか? というのはループの中でキー(スイカとか、メロンとか)が同じ 場合は$Data[$log2]が上書きされるということです。 6回ループして結果が3行ということは3回は上書きされたということです。 >$log1 には私のソース上では、【log.txt の中身】の数字のところが代入される仕組みになっていますが 何故、$log1 を $Data[$log2]に代入するのでしょうか? これについては代入する意味はループの動きが分かりやすくなるという以外特にないです。 $Data[$log2]=""; としてもよいでしょう。 >私には、foreachの関数の仕組みの意味がわかりません。汗 foreach((array)$Data as $key=>$value) というのは $Dataは配列 $keyには$Dataという配列のキー、 $valueには$Data["$key"]の値が入ります。 foreach文は$Data配列を一つずつ読んで配列が終わるまで繰り返し ます。 $Dataの前の(array)は、$Dataが配列でない場合、foreachで エラーを起こすので記述しました。 ここまで説明しておいてなんですが、 No3の方の言うようにarray_uniqueという関数を使うのがスマートだと思いました。
その他の回答 (3)
- yambejp
- ベストアンサー率51% (3827/7415)
普通にarray_uniqueすればいいんじゃないのかなぁ? <?PHP $handle = fopen("log.txt", "r"); while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) { if(isset($data[1])) $fruit[]=$data[1]; } fclose($handle); $unique_fruit=@array_unique($fruit); if(is_array($unique_fruit)) foreach($unique_fruit as $val) print $val."<br>"; ?>
補足
PHP5の本を読み勉強したと時、最初は、array_unique (重複した値を取り除く関数)を使用し色々試していましたが、array_unique 関数を使用は、単に array 関数の配列に対しては効率が良いのですが、今回の場合、ファイルの中身のデータは何も書き換えず、そのまま、ブラウザ表示の際だけ重複した値を取り除き表示させたかったので array_unique 関数を使用すると複雑になるので使用を断念しました。 今回、この場でご回答下さった皆さんのご回答は、私にとっては非常に参考になりました。 結果、それ事を独学で勉強し踏まえた上で応用し、解決する事ができました! 私の応用とは、変数 $log2 の出力チェックを array_key_exists 関数を使用し行う事でループを短縮させ効率よく解決できました。 (これまでに 変数 $log2 が出力した事が有るかをチェック) 今回は、皆さんのそれぞれのご回答のおかげです。 この度はご回答下さり本当に有り難う御座いました。 また質問した際は、ご指導の程、宜しくお願い致します。
- wp_
- ベストアンサー率54% (132/242)
>私には、foreachの関数の仕組みの意味がわかりません。 マニュアルをあと42回読みましょう。 まにゅある foreach http://jp2.php.net/foreach foreach($ループさせる配列 as $ハッシュのキー => $ハッシュの値) { これが使えなくてはphpでプログラミングするときにお話になりません。 ぜひマスターしましょう。 $arr = array("key1"=>"value1","key2"=>"value2"); foreach($arr as $k => $v) { echo $k . "/" . $v . "\n"; } 上記は以下になります。 key1/value1 key1/value2 さて命題ですが、まずやりたいことを順序だてて整理しましょう。 ・ファイルからデータを読み込む ・読み込んだデータをカンマ区切りで連想配列に格納 ・格納した連想配列でループ ・出力用の一時変数に既に値(value)があれば何もしない ・出力用の一時変数に値がなければ一時変数に格納 ・ループが終わったときechoする //・ファイルからデータを読み込む $log = file("log.txt"); //・読み込んだデータをカンマ区切りで連想配列に格納 $fileData = array();// 初期化 for($i=0;$i<sizeof($log);$i++){ list($log1,$log2) = explode( "," , $log[$i]); $fileData[$log1] = $log2; } //・格納した連想配列でループ $dataOutput = array(); //出力用の一時変数を初期化 foreach($fileData as $key => $value) { // ・出力用の一時変数に値がなければ一時変数に格納 if(in_array($value,$dataOutput)) { $dataOutput[] = $value; } // ・出力用の一時変数に既に値(value)があれば何もしない else { } } // ・ループが終わったときechoする print_r($dataOutput); サンプルソースをみて知らない関数、知らないロジックが出てきたら以下のようにして調べましょう。 http://www.google.co.jp/search?hl=ja&q=site%3Aphp.net+in_array&lr= マニュアルから検索しても良いですが。 >No.1 そのロジックはvalueが文字列であると言う大前提を崩す可能性があり、非常に危険で悪質なコードであると言えます。 valueの仕様で絶対に例外が存在しない確定されたものであるという以外では使用すべきロジックではありません。 少なくともこういった場で出すべきサンプルではありません。
補足
>マニュアルをあと42回読みましょう。 ↑前文は私にとっては手厳しいご回答でしたが、しかし、中文では、参考になりました。 今回、この場でご回答下さった皆さんのご回答は、私にとっては非常に参考になりました。 結果、それ事を独学で勉強し踏まえた上で応用し、解決する事ができました! 私の応用とは、変数 $log2 の出力チェックを array_key_exists 関数を使用し行う事で、ループを短縮させ効率よく解決できました。 (これまでに 変数 $log2 が出力した事が有るかをチェック) 今回は、皆さんのそれぞれのご回答のおかげです。 この度はご回答下さり本当に有り難う御座いました。 また質問した際は、ご指導の程、宜しくお願い致します。
- fa-ce
- ベストアンサー率42% (9/21)
一番近道ですが、 $log = file("log.txt"); for($i=0;$i<sizeof($log);$i++){ list($log1,$log2) = explode( "," , $log[$i]); //ここで、$log2をキーにした配列を作ります。 //キーが同じの場合は$Data[$log2]は上書きされますが //特に$log1の値は必要ないようなので・・・ $Data[$log2] = $log1; //この下のプリントはコメントアウトで。 //print "$log2<br>\n"; } foreach((array)$Data as $key=>$value) echo $key; で出来ると思います。 テストしていませんので確かめてください。 $log1の値でソートなどしたいようなら、別のことを考えるか、 ソート関数で並べ替えをしてからのほうが良いでしょう
補足
この度は早々にご回答下さり有り難う御座います。 私は、PHPを覚えた手なのであまり詳しい関数とか仕組みが今一よく分りません。汗 >//ここで、$log2をキーにした配列を作ります。 どのように配列を作ってよいのか分りません。汗 >//キーが同じの場合は$Data[$log2]は上書きされますが $Data[$log2]の変数は、どこを意味しているのでしょうか? また、どこで上書きされるのでしょうか? >$Data[$log2] = $log1; $log1 には私のソース上では、【log.txt の中身】の数字のところが代入される仕組みになっていますが 何故、$log1 を $Data[$log2]に代入するのでしょうか? >foreach((array)$Data as $key=>$value) 私には、foreachの関数の仕組みの意味がわかりません。汗 もし宜しければ、以上の事を再度詳しく教えて頂けると嬉しく想います。
お礼
この度、再度私の質問に対しご回答下さり有り難う御座います。 非常に、詳しく明確な説明と共に丁寧なご回答下さったおかげで、私にも理解する事ができました。 今回特に、そのおかげで理屈が理解できたので応用するきっかけに大変役立ちました! 本当に助かりました。感謝しています。 また今回、この場でご回答下さったその他の皆さんのご回答も、私にとっては非常に参考になりました。 結果、それ事を独学で勉強し踏まえた上で応用し、解決する事ができました! 私の応用とは、変数 $log2 の出力チェックを array_key_exists 関数を使用し行う事で ループを短縮させ効率よく解決できました。 (これまでに 変数 $log2 が出力した事が有るかをチェック) また質問した際は、ご指導の程、宜しくお願い致します。