PHPでCSVから条件にあう行を取得する方法

このQ&Aのポイント
  • PHPを使用してCSVファイルから条件に合致する行を取得する方法について教えてください。
  • 安い果物の情報を取得する方法と、安い果物がない場合には価格に近い果物の情報を取得する方法について説明します。
  • 具体的な実装方法や注意点なども教えていただけると助かります。
回答を見る
  • ベストアンサー

PHP CSVから条件にあう行を3行取りだしたい

以下のようなCSVがあったとします。(data.csv)価格で降順にソートしてあります。 line0,line1,line2 1,ぶどう,200(円) 2,なし,150(円) 3,りんご,100(円) 4,バナナ,80(円) 5,みかん,50(円) ある果物を紹介するページがあったとして、 そのページには、他のオススメの果物として、csvからデータを読み込み、 その果物よりも安いもの3件を表示するという仕組みを作ろうと思っています。 ただ、安いものが3件無かった場合に、それよりも高いが、それに近い価格の果物を あわせて3件まで紹介したいと思っています。 今作っているPHPは以下の通りです。 ページに紹介されている果物=($fruits),価格=($price) です。 <?php $Data=file('/data.csv'); $j=0; for($i=0;$i<sizeof($Data);$i++){ $line=explode(",",$Data[$i]); #表示ページの果物とCSVのline1が違い、価格が$priceよりも小さいものを3件まで表示 if($fruits != line1 and $price >= line2 and $j<3 ){     echo $line1 $line2.' </br>'; $j++; } } ?> で、価格が低いものを3件まで表示することはできました。 ぶどう200円のページであれば、 2,なし,150(円) 3,りんご,100(円) 4,バナナ,80(円) が表示されるようにはできました。 りんご100円のページには、 4,バナナ,80(円) 5,みかん,50(円) の2件のみが表示されています。 上記りんごのように、安いものが3件なかった場合に、 それより価格が高いが一番近いものから順に3件になるまでデータを 取りだしたいと思っています。 今回のりんごであれば、リンゴより安い、バナナ80円、みかん50円、 それに加え、リンゴより高いがリンゴの価格に一番近い、なし150円を表示させたいです。 みかんの場合には、安いものがないため、高いがみかんに近いものから3つ 2,なし,150(円) 3,りんご,100(円) 4,バナナ,80(円) を表示させたいです。 一体どうしたら良いのか、検討も付かず、教えて頂きたいです。 よろしくお願い致します。

noname#163772
noname#163772
  • PHP
  • 回答数2
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • JaneDue
  • ベストアンサー率75% (263/350)
回答No.2

>その季節条件が同じものだけでとか~ 価格以外の条件も参照するなら先の方法はマズいです。素直にデータを1つづつ回した方がよいでしょう。またfile()よりもfgetcsv()なら自動的に配列にしてくれるのでそちらがよいかと。 if(!$fh = fopen("data.csv", "r")) die("読み込み失敗"); $high = array(); $low = array(); while (($line = fgetcsv($fh, 1024, ",")) !== FALSE){ //自分なら何もしないで次へ if($line[1] === $fruits) continue; //以下でいろいろな条件を。例:季節が違えば無視して次へ if($line[3] !== $季節) continue; //条件をクリアしたら、高いものは逆順にしたいので先頭に入れていく if( (int)$line[2] >= (int)$price){ array_unshift($high,$line); //安いものは$lowの後ろに追加していく }else{ array_push($low,$line); } } //$lowと$highをくっつけて欲しい件数に切り詰めて… $reco = array_splice(array_merge($low,$high),0,3); //表示 print_r($reco); ※基本的に一気に出力しようとせず、1.処理(一旦必要なデータを作成する) 2.表示 にした方があとあと幸せになれます。煩雑な処理の上ましてやテーブルでの表示まで入ってくると自分でもわけが分からなくなって修正が大変です。 また、データは価格の降順なのに安いものが優先なので、処理が難しく感じられるのでしょう。 もしデータも昇順なら、現在の商品が出てきた段階で必要なオススメ件数が集まっていれば無駄なことをせずループ(forやwhile)から抜け出せます。件数が足りず自分より高いものが必要な場合でも、件数が集まった時点で終了できます。 ※価格に(円)が入っているため、(int)$price として強制的に数字として評価していますが、思わぬ値になることもあります。価格に限らず、計算するものは数字だけの方が簡単ですよ。 思い通りに動いてくれた時は格別ですよね。頑張って下さい。

noname#163772
質問者

お礼

随分とお礼が遅くなったのですが、いろいろ試行錯誤しながら、できるようになりました。 基本的な考え方や、csvの事などまでご丁寧にアドバイス頂き、本当に感謝しています。 ありがとうございました!

その他の回答 (1)

  • JaneDue
  • ベストアンサー率75% (263/350)
回答No.1

いろいろな方法があると思いますが、考え方の一例として。 オススメしたい順番とはつまり、 [直近の安い商品(降順)] + [直近の高い商品(昇順)] の配列を作って、先頭からオススメ件数を取得すればよい、ということになりますよね? //現在のページデータ。(line0はid? も既知としています) list($id,$fruits,$price) = array(3,"りんご","100(円)"); $Data=file('data.csv'); //自分(現在の商品)が何番目か$nにキーを取得。りんごの場合なら[2]。 $n = array_search("$id,$fruits,$price\n",$Data); //自分より安いものと高いものに分割する。 //安いもの--自分の次からが安いものなので、$n+1以降を$lowに取得 $low = array_splice($Data,$n+1); //高いもの--残りをひっくり返して昇順に。[0]は自分なのでその次、つまり[1]以降を取得する。 $high = array_splice(array_reverse($Data),1); //2つの配列をくっつけて欲しい件数を取得。 $reco = array_splice(array_merge($low, $high),0,3); //後はforeachなどでお好きに整形出力 print_r($reco); ※動いているようですのでツッコミませんが、細かいタイプミスが多いのが気になります。 また操作しづらいのでcsvには通常(円)は入れない方がよいかと。

noname#163772
質問者

補足

JaneDueさん ありがとうございます。 うまく3行取り出せそうです。 先に必要な行を取り出すことで、スピードも向上しそうな気がしています。 3行取り出す時の条件として、例えば、100円以上のものだけとか、例えば果物の季節をCSVに入力しておき、その季節条件が同じものだけで、上記の3行を取り出すといったことは可能なのでしょうか? >※動いているようですのでツッコミませんが、細かいタイプミスが多いのが気になります。 >また操作しづらいのでcsvには通常(円)は入れない方がよいかと。 ありがとうございます。 本当に、初心者の初心者であるため、不勉強な部分が多く恥ずかしいです>< また、何かあればなんでもおっしゃって下さい。

関連するQ&A

  • array_reverse()の使い方について

    array_reverse() の使い方が分かりません・・・。 CSV(降順)のデータを読み込んでPHPで表示する仕組みを作っています。 そのCSVを昇順にしたく、array_reverse() を使っても、思うようにデータが表示されません。 CSV(data.csv)は以下の通りです。価格で降順になっているものです。 line0,line1,line2 1,ぶどう,200(円) 2,なし,150(円) 3,りんご,100(円) 4,バナナ,80(円) 5,みかん,50(円) PHPは以下の通りです。 <?php $Data=file('/data.csv'); $j=0; for($i=0;$i<sizeof($Data);$i++){ $line=explode(",",$Data[$i]); if($j<3 ){ echo $line1 $line2.' <br />'; $j++; } } ?> $Data を 昇順にしたいので(もともとのCSVを昇順で作ることはできません)、 array_reverse($Data) をどこかに入れたらいいと思うのですが、forの前、後ろといろいろ入れてみたのですが、思ったように表示がされず困っています。 お力おかしください!!!よろしくお願いします。

    • ベストアンサー
    • PHP
  • R で日付を条件に抽出

    以下のような CSV で 2014-05-01 から 2014-05-31 までのデータを抽出するにはどのようにすればよいでしょうか test.csv name price date キウイ 80 2014-04-29 バナナ 150 2014-04-30 リンゴ 100 2014-05-01 ミカン 200 2014-05-02 : 以下同様に6月のデータも少し含まれる CSV ファイルを読み込む

  • 膨大な量のcsvファイル(ファイル数1000件以上)から条件にあったセル位置を抜き出したいです

    よろしくお願いします。 手元に大量のcsvフィルがあります(ファイル数1000件以上)。 何種類かのデータが上から順に入力されていて A列にその行のデータの種類が数字で示されているような体裁になっています。 例) 1枚のcsvシートに上から「各店舗でのりんごの小売価格」「みかんの小売価格」「バナナの小売価格」がまとめられていて(価格などの情報はB列以降に記載) 「りんご」「みかん」「バナナ」という種類がA列に「1」「2」「3」のような数字で示されている感じです。 1~4行がりんごのデータ、5・6行がみかん、7~9がバナナのデータという具合です。   A B C D ------------------------------- 1|1|100 2|1|120 3|1|90 4|1|100 5|2|50 6|2|30 7|3|100 8|3|150 9|3|100 これでみかんのデータの開始と終了のセル位置を(例の場合だと「A5」「A6」) 別のファイルのシートに一覧にしたいのです。 この例だと5~6行と簡単ですが、実際のcsvファイルはデータ量が膨大なため、この間の行数は数百行にのぼります。 各ファイルともだいたいセル位置が似通っているので今までは適当にジャンプ検索して目で確認していましたが、ファイル数が多すぎて手作業でやるには作業の負荷的に厳しいです。 私は普通の事務員なので自分で何かプログラムするというのは難しいと思います。 csvやエクセルのワザ、もしくはおすすめのフリーソフトなどでこれを解決できたらと思っています。 どうかご教授ください!

  • 例えばPHPで下記のようなdata.csvがあります

    例えばPHPで下記のようなdata.csvがあります NO,種類,入荷日,出荷日 1,りんご,2010/06/10,2010/06/30 2,みかん,2010/03/10,2010/04/30 3,かき,2010/05/10,2010/05/30 ・ ・ ・ これらをPHPで読み込んできて入荷日順に10件ずつ表示するプログラムを書きたいのですが 本も三冊買ってきたり、掲示板のソースとかをみて参考にできるかと思ったりしたのですが当方初心者でしてどうも難しく行き詰っております。 data.csvから1行ずつ取り込んできて、3番目の数字でソートするといいというのは分かるのですが どうもその方法がわかりません。 何かアドバイス頂ければ幸いです。

    • ベストアンサー
    • PHP
  • EXCEL 複数列条件に一致する行を数えるには

    添付画像のデータのB2:E17中で項目α~θが完全一致する都道府県の数をF列の「件数」に表示出来る関数はありますか? 添付画像だと 岩手と山梨:りんご・バナナ・みかんで一致→2 山形と千葉:りんご・みかん・みかんで一致→2 栃木と東京:バナナ・みかん・りんごで一致→2 それ以外は1という感じです。 宜しくお願いします。

  • PHP SQL 問合せについて

    PHP SQL 問合せについて http://okwave.jp/qa/q7689206.html での質問の続きとなります。 No,name 1,ばなな 2,りんご 3,ばなな 4,みかん 5,ばなな 6,りんご 上記テーブルで 1,ばなな 3,ばなな 5,ばなな 2,りんご 6,りんご 4,みかん の結果を得るSQLはどのように記述すればよいでしょうか? 回答 select * from tableA x order by (select count(*) from tableA y where y.name = x.name ) ,No で解決していますが、 select * from tableA x where name ='果物' とした場合、結果が異なります。 (結果が多い順にならない) 出現回数が多い順に並べるには、どのような記述になりますか? データには「果物以外のデータが含まれている」とします。 宜しくお願い致します。

    • 締切済み
    • PHP
  • PHPで指定件数のデータを表示させる方法

    お世話になっております。 下記のようなPHPブログラムでitem.csvのデータをランダムに指定件数表示させようと思っています。 このままですとデータは1件か2件表示され、$i<=3にすると2件か3件表示されます。 require_once('common.php'); $Data=file('item.csv'); shuffle ($Data); for ( $i=1; $i<=2; $i++ ){ $line=explode(",",$Data[$i]); print($line[2]); print($line[3]); } これを1を設定すれば1件、3を設定すれば3件というように、数字の件数を表示させたいと思います。 ご教授いただければ幸いです。よろしくお願いいたします。

    • 締切済み
    • PHP
  • 重複する不要な行を消し、必要行のみを残したい

    下表のエクセルがあります。果物の種類はたくさん、4月から3月までの表で、みかんの2行目は1行目に5月のデータが追加されたものです。2行目があれば1行目はいらないので2行目だけを残し、1行目は非表示にして別シートに移したいのですが、うまい関数やマクロを教えてください。 A列  B列   C列  D列 果物   4月    5月   計 みかん   2         2 みかん   2     5   7 りんご   3        3 りんご   3     7   10 これを別シートに移す(不要行を削除して) 果物  4月  5月  計 みかん 2   5   7 りんご 3   7   10

  • CSVファイルの内容をまとめて表示するには

    現在CSVの内容をまとめて表示する方法を思考しています。 例えば(data.csv) ========================= [ID][名前][好きなページURL] [01][山田][http://yahoo.co.jp] [02][鈴木][http://google.co.jp] [03][山田][http://www.goo.ne.jp] [04][加藤][http://google.co.jp] [05][武田][http://yahoo.co.jp] ・ ・ ・ ============= 各項目はカンマ区切りのcsvファイルです。 このCSVファイルを下記のようにまとめて表示する方法を検討しています。 <集計結果表示> 書き込み件数 山田:2件 鈴木:1件 加藤:1件 武田:1件 <好きなURL集計結果> http://yahoo.co.jp = 2件 http://google.co.jp = 2件 http://www.goo.ne.jp = 1件 =========================-- といった具合です。 自分で考えたプログラムを下記に記載します。 <?PHP $Data = file("data.csv"); for($i=0;$i<sizeof($Data);$i++){ $line = explode(",",$Data[$i]); list($id,$name,$url) = $line; ここに名前の集計ができるプログラムを考えています。ここがわからず悩んでいます。 } echo "書き込み件数:{$n}件" ?> 名前の集計の方法がわかればURLの集計も同様の方法で解決が可能だと思うのです。 大変恐縮ですが、お教えいただけないでしょうか。 宜しくお願いいたします。

    • ベストアンサー
    • PHP
  • CSVファイルからタイトル別一覧表示

    CSVファイルからタイトル別一覧表示 PHP初心者です。質問させてください。 以下のようなCSVファイルを読み込み、2列目の値をタイトルに一覧を作りたいのですが ループの中でどのように表記すればよいのでしょうか? 0,アイテム1,りんご 0,アイテム2,さば 1,アイテム1,グレープ 0,アイテム1,バナナ 0,アイテム2,いか <?php $array = file("shopdata.csv"); foreach($array as $line){ $line = explode("," , $line); if($line[0] == "0"){ echo '$line[1]'; echo '<ul>'; echo '<li>'.$line[2].'</li>'; } } ?> </ul> 以下のように表示したいのですが、上記では「$line[1]」もループしてしまい一覧になってしまいます。 アイテム1 <ul> <li>りんご</li> <li>バナナ</li> </ul> アイテム2 <ul> <li>さば</li> <li>いか</li> </ul> このように表示するにはどういった記述をすればいいのでしょうか? ご教示いただけますでしょうか。

    • 締切済み
    • PHP