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

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

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Q&A

2回答

4646閲覧

PHPでVLOOKUPの関数を作りたい

Chelsea_10

総合スコア46

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

0グッド

1クリップ

投稿2016/07/27 02:42

編集2016/07/27 02:53

phpのプログラムについてですが・・・
エクセルのVLOOKUP関数みたいな関数をphpで作れますか?

csv形式で、下記のようなデータが入っており、配列として出力したいのですが、
csvデータを読み取り1行ごとに配列に格納することはできたのですが、その後の処理がわかりません。。
なお、名前が重複している箇所は、最短取得の場合は上のデータを全取得の場合は、全てのデータを取るような形式にしたいです。
VLOOKの指定範囲については、csvデータ全体なので引数として範囲を設定しなくてもOKです。

data.csv

-, 出場回数,ゴール,カードをもらった数,(去年の)出場回数,(去年の)ゴール,(去年の)カードをもらった数
高橋, 10, 2, 1, 20, 5, 3
佐藤, 15, 4, 3, 21, 7, 4
鈴木, 12, 5, 2, 22, 5, 5
中村, 14, 6, 4, 44, 8, 6
国分, 15, 3, 5, 22, 9, 3
鈴木, 16, 4, 6, 18, 3, 1

成功例

php

1<?php 2//全取得で鈴木選手のゴール数の値を取得する場合 3$ret = $cl->execute("v","鈴木",2,true) 4var_dump($ret); 5array(2) { 6 [0] => 7 string(1) "5" 8 [1] => 9 string(1) "4" 10} 11?>

なお見つからなかった場合は

php

1<?php 2//全取得で鈴木選手のゴール数の値を取得する場合 3$ret = $cl->execute("v","鈴木",99,true) 4var_dump($ret); 5array(1) { 6 [0] => 7 string(4) "#N/A" 8} 9?>

と返す。

今書いているコードを共有いたします...

php

1<?php 2 //data.csvを読み込み1行ごとに配列に落としこむ処理 3 function execute($csvFile) { 4 //table.csvの読み込み 5 $csvFile = __DIR__ ."/data.csv"; 6 7 //文字コード変換 8 $csvData = mb_convert_encoding(file_get_contents("$csvFile"),'UTF-8','ASCII,JIS,UTF-8,EUC-JP,SJIS'); 9 10 //改行で分割 11 $csvLine = explode("\n",$csvData); 12 return $csvLine; 13 } 14 15 16 $csvFile =__DIR__ ."/data.csv"; 17 $ret = execute($csvFile); 18 var_dump($ret); 19?>

かなり初歩的なことしか進んでなく、情けないですが何卒ご教授お願いいたします。。。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

とりあえずざっと走査すればよいような

//test.csv

csv

1"a","b","c","d","e","f","g" 2"高橋","10","2","1","20","5","3" 3"佐藤","15","4","3","21","7","4" 4"鈴木","12","5","2","22","5","5" 5"中村","14","6","4","44","8","6" 6"国分","15","3","5","22","9","3" 7"鈴木","16","4","6","18","3","1"

PHP

1<?PHP 2$fp=fopen("test.csv","r"); 3while (($d = fgetcsv($fp, 1000, ",")) !== FALSE) { 4$data[]=$d; 5} 6fclose($fp); 7function vlookup($data,$name,$col,$flg){ 8 $ret=[]; 9 foreach($data as $vals){ 10 if($vals[0]==$name){ 11 $ret[]=$vals[$col]; 12 if($flg) break; 13 } 14 } 15 if(count($ret)==0) $ret[]="#N/A"; 16 return $ret; 17} 18 19var_dump(vlookup($data,"鈴木",2,true)); 20var_dump(vlookup($data,"鈴木",2,false)); 21var_dump(vlookup($data,"田中",2,false)); 22?>

※ファイル化配列への取り込みはfgetcsvなどご利用ください
→fgetcsv用にソースを修正しておきました

"v"の仕様が提示されてないので省略しました
最短取得・全取得はどちらがtureかわからなかったので
とりあえず最短取得=trueとしてあります
桁あふれや型のチェックなどおこなっていないので必要にあわせて処理をいれてください

データ量が多い場合はsqliteやその他RDBをご利用されたほうがよいかも

投稿2016/07/27 03:40

編集2016/07/27 04:26
yambejp

総合スコア114810

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Chelsea_10

2016/07/27 04:03

ご教授いただきましてありがとうございます。。 ですが申し訳ございません。。 そこに至るまでの仮定に辿りつけていないです。 $data=[ ["a","b","c","d","e","f","g"], ["高橋","10","2","1","20","5","3"], ["佐藤","15","4","3","21","7","4"], ["鈴木","12","5","2","22","5","5"], ["中村","14","6","4","44","8","6"], ["国分","15","3","5","22","9","3"], ["鈴木","16","4","6","18","3","1"], ]; 上記の関数を実行するまでの下準備ですが、下記の通りではだめなのでしょうか?? ちなみに関係あるかどうかわかりませんが、 PHPのバーションは5.3です。 <?php //data.csvを読み込み1行ごとに配列に落としこむ処理 function execute($csvFile) { //table.csvの読み込み $csvFile = __DIR__ ."/data.csv"; //文字コード変換 $csvData = mb_convert_encoding(file_get_contents("$csvFile"),'UTF-8','ASCII,JIS,UTF-8,EUC-JP,SJIS'); //改行で分割 $csvLine = explode("\n",$csvData); return $csvLine; } $csvFile =__DIR__ ."/data.csv"; $ret = execute($csvFile); var_dump($ret); ?> これだけでは足りないのでしょうか。
yambejp

2016/07/27 04:29

csvファイルは専用の読み込み関数があるのでそちらを利用したほうが楽です。 その他str_getcsv()や適当なライブラリを利用してもよいでしょう
Chelsea_10

2016/07/27 06:16

なるほど。。。 ありがとうございます! 現状おそらくきちんとデータがとれているとは思うのですが、 漢字などが文字化けしてしまっている状況です。 いろいろ策を講じてみたのですが、なかなかうまくいかなくて。。。 原因をお教えいただけますと助かります・・ <?php mb_internal_encoding("UTF-8"); $fp=fopen("table.csv","r"); while (($d = fgetcsv($fp, 1000, ",")) !== FALSE) { $data[]=$d; } var_dump($data); → [1]=> array(7) { [0]=> string(7) "C�`���[" [1]=> string(5) "3" [2]=> string(2) "28" [3]=> string(2) "30" [4]=> string(5) "4" [5]=> string(2) "21" [6]=> string(2) "19" fclose($fp);
yambejp

2016/07/27 06:54

取り込み後mb_convert_variables()を実行して適正な文字コードにしてください CSVがSJISでUTF8に変えたいなら、こんな感じ mb_convert_variables("UTF8","SJIS",$data);
Chelsea_10

2016/07/27 07:20

ご回答いただきありがとうございます。 そちらやってみたのですが、少し解消されたのですが Cってなってしまって。。。 解消されないです。。 下記ソースコード <?php mb_internal_encoding("UTF-8"); $fp=fopen("table.csv","r"); while (($d = fgetcsv($fp, 1000, ",")) !== FALSE) { $data[]=$d; } mb_convert_variables("SJIS","UTF8",$data); var_dump($data); fclose($fp); [1]=> array(7) { [0]=> string(3) "C`[" [1]=> string(5) "0.468" [2]=> string(2) "28" [3]=> string(2) "30" [4]=> string(5) "0.421" [5]=> string(2) "21" [6]=> string(2) "19" }
yambejp

2016/07/27 07:30

変換元と変換先のキャラクターコードが逆では? また2列目以下元ソースで提示されたデータとは違うようですが 指定したファイルが違うとかありませんか?
Chelsea_10

2016/07/27 11:11 編集

ごめんなさい、そちらのcsv名ですが、ちょっとリネームしてました。 ただ状況は先程共有したとおりでした。 ただ下記コードへ直しましたら、どういうわけか直りましたので共有いたします。 //data.csvの読み込み $csvFile = __DIR__ ."/data.csv"; //文字コード変換 $csvData = mb_convert_encoding(file_get_contents($csvFile),'UTF-8','ASCII,JIS,UTF-8,EUC-JP,SJIS'); //改行で分割 $csvLine = explode("\n",$csvData); foreach($csvLine as $csv) { $data[] = explode(",",$csv); } function vlookup($data,$name,$col,$flg){ $ret=array(); foreach($data as $key=> $d){ if($d[0] == $name){ $ret[] = $d[$col]; //もし$flgがtrueならbreak if($flg === true) { break; } } } if(count($ret)==0) { $ret[]="#N/A"; } return $ret; }
Chelsea_10

2016/07/27 11:13

ただ一点問題がございまして、 var_dump(vlookup($data,"違う名前",2,false));ならきちんと array(1) { [0]=> string(4) "#N/A" } と出力してくれるのですが var_dump(vlookup($data,"鈴木",55,false)); とするとエラーがでてしまいます。 同じように array(1) { [0]=> string(4) "#N/A" } とさせたいのですが、どのようにすればいいでしょうか。。。
guest

0

php

1$csv = array( 2 "高橋"=>array( "レコード番号" => array("高橋",10, 2, 1, 20, 5, 3)), 3 "鈴木"=>array( "レコード番号" => array("鈴木",10, 2, 1, 20, 5, 3) 4 , "レコード番号" => array("鈴木",10, 2, 1, 20, 5, 3)), 5); 6# 名前の番号が欲しい場合は以下で取得 7$names = array_keys($csv);

という連想配列に置き換えれば VLOOKUP(完全一致のみ)はできるはずです。

※ HLOOKUP(完全一致のみ) は $csv 作成時に縦横入れ替えればいいだけ

(動作確認してないので多少のミスあるかも)

完全一致の場合

php

1$result = array_filter(function($v, $k) use ($name) { 2 return strcmp($name, $k) === 0; 3});

#$ 部分一致の場合

php

1 2$result = array_filter(function($v, $k) use ($name) { 3 return preg_match("/{$name}/", $k); 4});

投稿2016/07/27 02:59

編集2016/07/27 03:38
asahina_dev

総合スコア610

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/07/27 03:05

そのCSVデータの持ち方をすると、鈴木さんが既に2人いる場合に対応できない気がします。
asahina_dev

2016/07/27 03:15 編集

その対応するとこんなかんじだね ※ 同じ名前が複数いたらの下りを見逃していた
Chelsea_10

2016/07/27 03:27

ご回答いただきありがとうございます。。。 こちら最短一致、全体一致どちらでも対応している形なのでしょうか?? foreachでいろいろ回して配列に組み込む形なのだろうなと、ふんわりとわかるのですが、そちらであっていますでしょうか。。。?
asahina_dev

2016/07/27 03:30

完全一致のみですね。 ループでごにょごにょすれば部分一致にも対応可能かと
Chelsea_10

2016/07/27 04:05

ご回答いただきありがとうございます。 大変助かります。 ただ、経験が浅いのと、考えが足りないのかそこまでになかなか辿りつけないです。 もうちょっとがんばってみます。。。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問