• ベストアンサー

連番を書き出すなどの単純処理をするこのコードを採点願えませんか

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 . "&nbsp;200412&nbsp;" . $i . "200412<br>\n";    } elseif ( $j == 2 ) {     $body .= $i . "&nbsp;200501&nbsp;" . $i . "200501<br>\n";    } elseif ( $j == 3 ) {     $body .= $i . "&nbsp;200502&nbsp;" . $i . "200502<br>\n";    } elseif ( $j == 4 ) {     $body .= $i . "&nbsp;200503&nbsp;" . $i . "200503<br>\n";    } elseif ( $j == 5 ) {     $body .= $i . "&nbsp;200504&nbsp;" . $i . "200504<br>\n";    } elseif ( $j == 6 ) {     $body .= $i . "&nbsp;200505&nbsp;" . $i . "200505<br>\n";    } elseif ( $j == 7 ) {     $body .= $i . "&nbsp;200506&nbsp;" . $i . "200506<br>\n";    } elseif ( $j == 8 ) {     $body .= $i . "&nbsp;200507&nbsp;" . $i . "200507<br>\n";    } elseif ( $j == 9 ) {     $body .= $i . "&nbsp;200508&nbsp;" . $i . "200508<br>\n";    } elseif ( $j == 10 ) {     $body .= $i . "&nbsp;200509&nbsp;" . $i . "200509<br>\n";    } elseif ( $j == 11 ) {     $body .= $i . "&nbsp;200510&nbsp;" . $i . "200510<br>\n";    } else {     $body .= $i . "&nbsp;200511&nbsp;" . $i . "200511<br>\n";    }   } } ?> <html> <body> <?= $body ?> </body> </html>

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

  • ベストアンサー
回答No.5

# 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}&nbsp;{$Ym}&nbsp;{$i}{$Ym}<br />\n"; } } こんなんどうでしょう? もっと数を増やして一番速いの、なんてやると面白いかもしれません。 案外、冗長な表現の方が速かったりします。forよりwhileの方が速い、と言う話もあったりしますし、、、

litton101
質問者

お礼

taketan_mydns_jpさん、レスありがとうございました。 コメントつきで、いかに処理するか、大変よく理解できました。 何より確かに超速で、一瞬で出力されたことに驚きました。 >案外、冗長な表現の方が速かったりします。forよりwhileの方が速い、 そういうものですか。確かに、#1さんのは 相当シンプルですが、わたしの元質問のダサいコードの方が 出力自体は早かったです。不思議なものですね。

その他の回答 (6)

  • aqucent
  • ベストアンサー率39% (78/200)
回答No.7

> # 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)."&nbsp;".$tmpStr."&nbsp;".$i.sprintf("%02d",$j).$tmpStr."<br>\n"; } } } #5, #6 の方のコードを参考にさせていただきました。

litton101
質問者

お礼

aqucentさん、たびたびのレス感謝にたえません、 > "20001" は 2000年1月を表し、"24000" は2400年0月(?)を表すのですね。   : > つまり、元々のコードに問題があるという事にならないでしょうか? いえ、元質問の例示の仕方が悪くてすみませんでしたが 「20001」の元データは、学籍番号みたいな主キーです。 2列目がyyyymm(ただし12月に始まり翌年11月で終わる繰り返し)でした。 for3段構えという入れ子も興味深く検証させていただきました。 ================== この場をお借りして解答くださった皆様へ 本件、締め切りますが、本当にありがとうございました。 本掲示板では、ポイントの形で御礼できますが、 ・一番速く処理/出力できるコードを提示くださったtaketan_mydns_jpさん、 ・最初にレスくださったnaktakさん につけさせていただきます、システム上気持ちは皆さんに差し上げたい気分ですので、 今後ともよろしくお願い致します。

  • yambejp
  • ベストアンサー率51% (3827/7415)
回答No.6

データ量が多いのでエクセルでやったほうがましです。 元質問にフォローしておきました。 簡単に書けば以下 <?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}&nbsp;{$tmpStr}&nbsp;{$i}{$tmpStr}<br>\n"; } } print $body; ?>

litton101
質問者

お礼

yamabejpさん、レスありがとうございました。 両方へのご教示、大変恐縮です。 yamabejpさんのは一番短いですね、 mktime使うところなどは、#5さんと似ているのですが、 やはり表示に10秒ほどかかりました。 確かに、エクセルでやったほうがぜんぜんよいかもしれません。 既にお気づきかと思いますが今回の処理は、↓の別解として、 SQLでの解決以外に、エキスポートした3テーブルをくっつけるのに、 VBAによる処理ではどうかという挑戦です。無論、yamabejpさんに 組んでいただいたSQLに大満足ではあります。 http://oshiete1.goo.ne.jp/kotaeru.php3?q=2269453

  • aqucent
  • ベストアンサー率39% (78/200)
回答No.4

#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 . "&nbsp;".$val."&nbsp;" . $key .$val. "<br>\n";  } } 連想配列を使用しているのがポイントです。 # 今度は検証済みです。 # 改めてみると、先程は私の頭が固すぎました(苦笑)

参考URL:
http://jp.php.net/manual/ja/control-structures.foreach.php
  • aqucent
  • ベストアンサー率39% (78/200)
回答No.3

すみません、ミスがありました。 #2 を以下のように修正いたします。 $body .= format_num(200412, $i); // ユーザー定義関数の呼び出し

  • aqucent
  • ベストアンサー率39% (78/200)
回答No.2

まず、 × elseif ○ else if ですね。 ---- $body .= $i . "&nbsp;200412&nbsp;" . $i . "200412<br>\n"; の下りをユーザー定義関数に function format_num($num, $i){  return $i . "&nbsp;".$num."&nbsp;" . $i .$num. "<br>\n"; } ---- if ($j==1){ の下りを switch に switch($j){  case '1':   format_num(200412, $i); // ユーザー定義関数の呼び出し   break;  case '2':   ... } # コードは実際に検証はしてませんが、多分動作すると思います。 ところで、"200412" 等の数値は定まった数なのですか? 規則性があるなら、変数にした方がコードが短くなると思います。 察するに何かの履歴ではないかと思うのですが、もしそうなら、何らかの形でログを残して、読み込んだ方が良いですね。

litton101
質問者

お礼

ユーザー定義関数ですか。 存在は知っていましたが使ったことなかったです、 こうやってサブルーチン化すれば、確かにコンパクトにできますね。 > ところで、"200412" 等の数値は定まった数なのですか? > 規則性があるなら、変数にした方がコードが短くなると思います。 あるといえばありますが、提示した法則性以上は見出せませんでした。 また、#4で提示いただいた配列というアイデアもありますね。 大変参考になりました。ありがとうございました。

回答No.1

こんなのでどうでしょうか? <?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."&nbsp;".$ym."&nbsp;".$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が重過ぎるだけかも。

litton101
質問者

お礼

naktakさん、早速のご回答ありがとうございました。 いやはや、確かにシンプルですね! 初学者のわたしにとっては使ったことのない 目新しい構文(defineとかstrtotimeとか。 無論やろうとしていることは理解できます) 確かに表示時間は少しかかるようで、 10秒ほどで完全に表示できました。

関連するQ&A

専門家に質問してみよう