- ベストアンサー
連番を書き出すなどの単純処理をするこのコードを採点願えませんか
Excel-VBAについて下記のような質問をしたのですが http://oshiete1.goo.ne.jp/kotaeru.php3?q=2285679 この質問で実現したい処理をPHPで例示してみて、もっとシンプルに かけるに違いない!と思っています。 実際、いかがなものでしょうか。 <?php for($i=20001;$i<=24000;$i++){ for ($j=1; $j<=12;$j++){ if ($j==1){ $body .= $i . " 200412 " . $i . "200412<br>\n"; } elseif ( $j == 2 ) { $body .= $i . " 200501 " . $i . "200501<br>\n"; } elseif ( $j == 3 ) { $body .= $i . " 200502 " . $i . "200502<br>\n"; } elseif ( $j == 4 ) { $body .= $i . " 200503 " . $i . "200503<br>\n"; } elseif ( $j == 5 ) { $body .= $i . " 200504 " . $i . "200504<br>\n"; } elseif ( $j == 6 ) { $body .= $i . " 200505 " . $i . "200505<br>\n"; } elseif ( $j == 7 ) { $body .= $i . " 200506 " . $i . "200506<br>\n"; } elseif ( $j == 8 ) { $body .= $i . " 200507 " . $i . "200507<br>\n"; } elseif ( $j == 9 ) { $body .= $i . " 200508 " . $i . "200508<br>\n"; } elseif ( $j == 10 ) { $body .= $i . " 200509 " . $i . "200509<br>\n"; } elseif ( $j == 11 ) { $body .= $i . " 200510 " . $i . "200510<br>\n"; } else { $body .= $i . " 200511 " . $i . "200511<br>\n"; } } } ?> <html> <body> <?= $body ?> </body> </html>
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
# 2の > × elseif > ○ else if は両方○だと思いますが。 http://php.s3.to/man/control-structures.elseif.html ま、どういう方法でも用は足りそうな気がしますが(笑。 for($i=0;$i<12;$i++){ $arr[] = date("Ym",mktime(0,0,0,12+$i,1,2004));//2004年12月から12ヶ月間の日付を配列に } for($i=20001;$i<=24000;$i++){ for($t=0:$t<12;$t++){ $Ym = $arr[$t%12]; //$t を 12で割った余り番の配列を$Ymに $body .= "{$i} {$Ym} {$i}{$Ym}<br />\n"; } } こんなんどうでしょう? もっと数を増やして一番速いの、なんてやると面白いかもしれません。 案外、冗長な表現の方が速かったりします。forよりwhileの方が速い、と言う話もあったりしますし、、、
その他の回答 (6)
- aqucent
- ベストアンサー率39% (78/200)
> # 2の > × elseif > ○ else if > は両方○だと思いますが。 知りませんでした。ご指摘ありがとうございます。 Excel-VBAのスレッドを読んで、今更ながら、コードの内容を理解しました。 "20001" は 2000年1月を表し、"24000" は2400年0月(?)を表すのですね。 そうなりますと、$i をインクリメントし続けると、10加算される度に繰り上げられますので、 11月,12月が考慮されないコードになってしまいます。 つまり、元々のコードに問題があるという事にならないでしょうか? for($i = 2000; $i < 2401; $i++){ for($j = 1; $j < 13; $j++){ for($k = 0; $k < 12; $k++){ $tmpStr = date("Ym",mktime(0,0,0,12+$k,1,2004)); $body .= $i.sprintf("%02d",$j)." ".$tmpStr." ".$i.sprintf("%02d",$j).$tmpStr."<br>\n"; } } } #5, #6 の方のコードを参考にさせていただきました。
お礼
aqucentさん、たびたびのレス感謝にたえません、 > "20001" は 2000年1月を表し、"24000" は2400年0月(?)を表すのですね。 : > つまり、元々のコードに問題があるという事にならないでしょうか? いえ、元質問の例示の仕方が悪くてすみませんでしたが 「20001」の元データは、学籍番号みたいな主キーです。 2列目がyyyymm(ただし12月に始まり翌年11月で終わる繰り返し)でした。 for3段構えという入れ子も興味深く検証させていただきました。 ================== この場をお借りして解答くださった皆様へ 本件、締め切りますが、本当にありがとうございました。 本掲示板では、ポイントの形で御礼できますが、 ・一番速く処理/出力できるコードを提示くださったtaketan_mydns_jpさん、 ・最初にレスくださったnaktakさん につけさせていただきます、システム上気持ちは皆さんに差し上げたい気分ですので、 今後ともよろしくお願い致します。
- yambejp
- ベストアンサー率51% (3827/7415)
データ量が多いのでエクセルでやったほうがましです。 元質問にフォローしておきました。 簡単に書けば以下 <?php for($i=20001;$i<=24000;$i++){ for ($j=0; $j<=11;$j++){ $tmpStr=date("Ym",mktime(0,0,0,12+$j,1,2004)); $body .= "{$i} {$tmpStr} {$i}{$tmpStr}<br>\n"; } } print $body; ?>
お礼
yamabejpさん、レスありがとうございました。 両方へのご教示、大変恐縮です。 yamabejpさんのは一番短いですね、 mktime使うところなどは、#5さんと似ているのですが、 やはり表示に10秒ほどかかりました。 確かに、エクセルでやったほうがぜんぜんよいかもしれません。 既にお気づきかと思いますが今回の処理は、↓の別解として、 SQLでの解決以外に、エキスポートした3テーブルをくっつけるのに、 VBAによる処理ではどうかという挑戦です。無論、yamabejpさんに 組んでいただいたSQLに大満足ではあります。 http://oshiete1.goo.ne.jp/kotaeru.php3?q=2269453
- aqucent
- ベストアンサー率39% (78/200)
#2です。 度々、失礼いたします。m(_ _)m $num = array(1 => 200412, 2 => 200501, 3 => 200502, 4 => 200503); for($i = 20001; $i < 24001; $i++){ foreach($num as $key => $val){ $body .= $key . " ".$val." " . $key .$val. "<br>\n"; } } 連想配列を使用しているのがポイントです。 # 今度は検証済みです。 # 改めてみると、先程は私の頭が固すぎました(苦笑)
- aqucent
- ベストアンサー率39% (78/200)
すみません、ミスがありました。 #2 を以下のように修正いたします。 $body .= format_num(200412, $i); // ユーザー定義関数の呼び出し
- aqucent
- ベストアンサー率39% (78/200)
まず、 × elseif ○ else if ですね。 ---- $body .= $i . " 200412 " . $i . "200412<br>\n"; の下りをユーザー定義関数に function format_num($num, $i){ return $i . " ".$num." " . $i .$num. "<br>\n"; } ---- if ($j==1){ の下りを switch に switch($j){ case '1': format_num(200412, $i); // ユーザー定義関数の呼び出し break; case '2': ... } # コードは実際に検証はしてませんが、多分動作すると思います。 ところで、"200412" 等の数値は定まった数なのですか? 規則性があるなら、変数にした方がコードが短くなると思います。 察するに何かの履歴ではないかと思うのですが、もしそうなら、何らかの形でログを残して、読み込んだ方が良いですね。
お礼
ユーザー定義関数ですか。 存在は知っていましたが使ったことなかったです、 こうやってサブルーチン化すれば、確かにコンパクトにできますね。 > ところで、"200412" 等の数値は定まった数なのですか? > 規則性があるなら、変数にした方がコードが短くなると思います。 あるといえばありますが、提示した法則性以上は見出せませんでした。 また、#4で提示いただいた配列というアイデアもありますね。 大変参考になりました。ありがとうございました。
- めとろいと(@naktak)
- ベストアンサー率36% (785/2139)
こんなのでどうでしょうか? <?php define("NM_START", 20001); define("NM_END", 24000); define("YM_START", 200412); $ym = YM_START; $body = ""; for($i = NM_START; $i <= NM_END; $i++) { for ($j = 1; $j <= 12; $j++) { $body.= $i." ".$ym." ".$i.$ym."<br>\n"; $ym = date("Ym", strtotime("+ 1 month", mktime(0, 0, 0, substr($ym, 4, 2), 1, substr($ym, 0, 4)))); } $ym = YM_START; } ?> <html> <body> <?= $body ?> </body> </html> 但し、PHPの制約か、私の環境が悪いのか、 文字列が正しく全部出力されませんでした。 PCが重過ぎるだけかも。
お礼
naktakさん、早速のご回答ありがとうございました。 いやはや、確かにシンプルですね! 初学者のわたしにとっては使ったことのない 目新しい構文(defineとかstrtotimeとか。 無論やろうとしていることは理解できます) 確かに表示時間は少しかかるようで、 10秒ほどで完全に表示できました。
お礼
taketan_mydns_jpさん、レスありがとうございました。 コメントつきで、いかに処理するか、大変よく理解できました。 何より確かに超速で、一瞬で出力されたことに驚きました。 >案外、冗長な表現の方が速かったりします。forよりwhileの方が速い、 そういうものですか。確かに、#1さんのは 相当シンプルですが、わたしの元質問のダサいコードの方が 出力自体は早かったです。不思議なものですね。