こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

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

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>

投稿日時 - 2006-07-19 15:18:01

QNo.2285688

暇なときに回答ください

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

# 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の方が速い、と言う話もあったりしますし、、、

投稿日時 - 2006-07-19 16:45:43

お礼

taketan_mydns_jpさん、レスありがとうございました。

コメントつきで、いかに処理するか、大変よく理解できました。
何より確かに超速で、一瞬で出力されたことに驚きました。

>案外、冗長な表現の方が速かったりします。forよりwhileの方が速い、

そういうものですか。確かに、#1さんのは
相当シンプルですが、わたしの元質問のダサいコードの方が
出力自体は早かったです。不思議なものですね。

投稿日時 - 2006-07-19 22:21:55

このQ&Aは役に立ちましたか?

3人が「このQ&Aが役に立った」と投票しています

回答(7)

ANo.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 の方のコードを参考にさせていただきました。

投稿日時 - 2006-07-19 17:34:59

お礼

aqucentさん、たびたびのレス感謝にたえません、

> "20001" は 2000年1月を表し、"24000" は2400年0月(?)を表すのですね。
  :
> つまり、元々のコードに問題があるという事にならないでしょうか?

いえ、元質問の例示の仕方が悪くてすみませんでしたが
「20001」の元データは、学籍番号みたいな主キーです。
2列目がyyyymm(ただし12月に始まり翌年11月で終わる繰り返し)でした。

for3段構えという入れ子も興味深く検証させていただきました。


==================
この場をお借りして解答くださった皆様へ

本件、締め切りますが、本当にありがとうございました。
本掲示板では、ポイントの形で御礼できますが、
・一番速く処理/出力できるコードを提示くださったtaketan_mydns_jpさん、
・最初にレスくださったnaktakさん
につけさせていただきます、システム上気持ちは皆さんに差し上げたい気分ですので、
今後ともよろしくお願い致します。

投稿日時 - 2006-07-19 22:43:15

ANo.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;
?>

投稿日時 - 2006-07-19 17:04:40

お礼

yamabejpさん、レスありがとうございました。
両方へのご教示、大変恐縮です。

yamabejpさんのは一番短いですね、
mktime使うところなどは、#5さんと似ているのですが、
やはり表示に10秒ほどかかりました。
確かに、エクセルでやったほうがぜんぜんよいかもしれません。

既にお気づきかと思いますが今回の処理は、↓の別解として、
SQLでの解決以外に、エキスポートした3テーブルをくっつけるのに、
VBAによる処理ではどうかという挑戦です。無論、yamabejpさんに
組んでいただいたSQLに大満足ではあります。
http://oshiete1.goo.ne.jp/kotaeru.php3?q=2269453

投稿日時 - 2006-07-19 22:33:00

ANo.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

投稿日時 - 2006-07-19 16:35:26

ANo.3

すみません、ミスがありました。
#2 を以下のように修正いたします。

$body .= format_num(200412, $i); // ユーザー定義関数の呼び出し

投稿日時 - 2006-07-19 16:13:54

ANo.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" 等の数値は定まった数なのですか?
規則性があるなら、変数にした方がコードが短くなると思います。
察するに何かの履歴ではないかと思うのですが、もしそうなら、何らかの形でログを残して、読み込んだ方が良いですね。

投稿日時 - 2006-07-19 16:09:54

お礼

ユーザー定義関数ですか。
存在は知っていましたが使ったことなかったです、
こうやってサブルーチン化すれば、確かにコンパクトにできますね。

> ところで、"200412" 等の数値は定まった数なのですか?
> 規則性があるなら、変数にした方がコードが短くなると思います。

あるといえばありますが、提示した法則性以上は見出せませんでした。
また、#4で提示いただいた配列というアイデアもありますね。

大変参考になりました。ありがとうございました。

投稿日時 - 2006-07-19 22:14:56

ANo.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が重過ぎるだけかも。

投稿日時 - 2006-07-19 16:07:02

お礼

naktakさん、早速のご回答ありがとうございました。
いやはや、確かにシンプルですね!

初学者のわたしにとっては使ったことのない
目新しい構文(defineとかstrtotimeとか。
無論やろうとしていることは理解できます)

確かに表示時間は少しかかるようで、
10秒ほどで完全に表示できました。

投稿日時 - 2006-07-19 21:55:35

あなたにオススメの質問