- ベストアンサー
集計データの取得方法とCSVファイルの値の取り出しについて
- アンケートスクリプトでフォームからPOSTされたデータを受けて、CSVファイル操作を行い、集計データを取得する方法について教えてください。
- CSVファイルの形式などについて指定はありませんが、1年を4分割してデータを取得する方法について教えてください。
- CSVファイルから特定範囲のデータを取得したい場合、localtimeを使用して日付を比較し、範囲を絞ってデータを取得する方法について教えてください。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
あ、失礼しました、実行チェックせずに投稿したら、微妙にいろいろ不具合が。。 不具合1 >@data2 = split( ',', $line2 ); ""の中にもカンマがあるので、カンマのみで分割すると、開始日と終了日も泣き別れになってしまう →先頭と最後の"を除いておいて、 「","」 で分割 $line2 = substr($line2, 1,-1); ###引数3つめ負数で末尾から削除 @data2 = split( '","', $line2 ); 不具合2 perlでは、ループから抜け出す時は、lastを使うのでした。 breakは、java,javascript,Cなどでの用語 →forループ内の break;を last;に置き換えて下さい 回答1 >>my $hantei=-1; >は、なぜマイナス1を入れているのでしょう?? 配列の添え字を$hanteiに入れるようにしていますが、 配列の添え字は0開始で最大値はいろいろ変動があるけど、どこかで判定に引っかかれば-1が入ることはあり得ないためです。 ループ終了後に-1であれば、最初の開始日よりも前である=最後の期間に入れる、としています。 回答2 >>for( $i=scalar(@data2)-1; $i>=0; $i-- ) >これは、要素数をforループの意味合いでいいですか? scalar(@data2)-1配列添え字の最大値から0へまでの減少ループです。 そういえば、 scalar(@data2)-1 → $#data2 っていう表現があったんでした。 ### forループ内のみ再掲 for( $i=$#data2; $i>=0; $i-- ){ $start = substr($data2[$i], 0,4); if( ($start cmp $dt) <=0 ){ # 開始日と同じかそれよりも後の日付の時 $hantei=$i; last; } } if( $hantei== -1){ $hantei= $#data2; }
その他の回答 (2)
- hrm_mmm
- ベストアンサー率63% (292/459)
>データ部は、"4月5日~6月12日","6月13日~9月20日","9月21日~12月15日","12月16日~4月5日"という意味 日付範囲に重なりは無いのですよね? 年越しするのは最後のデータのみなら、開始日だけを文字列の大小比較すればいけるのでは? ### $line2 に2行目を読み込んだとして @data2 = split( ',', $line2 ); my ($i,$start); my $hantei=-1; for( $i=scalar(@data2)-1; $i>=0; $i-- ){ $start = substr($data2[$i], 1,4); if( ($start cmp $dt) <=0 ){ # 開始日と同じかそれよりも後の日付の時 $hantei=$i; break; } } if( $hantei== -1){ $hantei= scalar(@data2)-1; } ### $hanteiに何番目の日付範囲に一致したかが入っている。
お礼
hrm_mmm様の提示されたコードを基に、なんとか 自己解決することが出来ました!! ありがとうございます。とても感謝です。
補足
hrm_mmm様、ご回答ありがとうございます。 >日付範囲に重なりは無いのですよね? はい、ありません。 開始日のみを大小比較…そういった発想が浮かびませんでした。 確かにそうですよね!今後の参考になります。 ところで、当方Perl初心者の為、解説して頂きたいのですが >my $hantei=-1; は、なぜマイナス1を入れているのでしょう?? それから >for( $i=scalar(@data2)-1; $i>=0; $i-- ) これは、要素数をforループの意味合いでいいですか? $line2 = '"0405,0530","0531,0904","0905,1025","1026,0404"'; として、実行したのですが「0」が返ってきてしまいます。 度々、申し訳ありませんが、ご教授下さい。
- hrm_mmm
- ベストアンサー率63% (292/459)
どこらあたりまで出来ているのか、ソースも提示していただかないと、ただの丸投げなので、あまり回答がつかないのでは? >このkeyごと(name1_~)にCSVファイルへ書き出したいです。 #FH にCSVファイルへ書き込み用 file handle設定して foreach (keys %in){ print FH $_ .','. $in{$_} . "\n"; # 一行ずつ出力 } close FH; >CSVファイルの値の取り出し >※2列目のデータは長くなってしまう為、3行に分けています。規則性はありません。 常に3行であることが確実ならば、ファイルの2-4行目は、読み込んだら終端の改行コードを削除(chomp)して連結してしまえば、 後は、split(',' , $line ) で、それぞれの列ごとに配列に格納出来ます。 何行繋げるかに規則がないとちょっと困るかも。 日付時刻別の振り分けは、どういう規則で、ファイルに書いてあって、どういう規則で取り出したいのかを詳細に記述してみて、まずは、ご自分で組んでみて下さい。
補足
hrm_mmm様、アドバイスありがとうございます。 確かに、丸投げ状態ですね…私自身、Perlをよく解っていないため、質問の要所をとらえて ないのかもしれません。 >#FH にCSVファイルへ書き込み用 file handle設定して こういう書き方で、ハッシュの値がファイルに取り出せるのですね! 大変、参考になりました。 >常に3行であることが確実ならば、ファイルの2-4行目は… これは、この投稿の見栄えをよくするために3行に分けたということで、本来は 1行になっている部分です。 ですから、実際のデータ行は3行になっています。 "0405,0612","0613,0920","0921,1215","1216,0404", というデータ部は、 "4月5日~6月12日", "6月13日~9月20日", "9月21日~12月15日", "12月16日~4月5日" という意味で、 本日日付を取得して ($ss, $mn, $hh, $dd, $mm, $yy, $yb) = localtime(time); $yy += 1900; $mm++; $str = (%02d%02d); $dt = sprintf($str,$mm, $dd); にて$dtは、データどの部分にマッチするのか? という結果を得たいのです。 配列への格納等は、出来るのですがこういったCSVデータを、日付の範囲に変えてマッチさせる やり方があれば教えて頂きたいと思っています。
補足
hrm_mmm様、 ご回答及びご丁寧な解説、とても助かります。 また、ご質問させてください。 戻り値の数値が例えば、「2」だとしたら「0612」 "0405,0612","0613,0920"→ 1 =「0405」,2 =「0612」,3 =「0613」,4 =「0920」 こんな感じになるのでしょうか? 最初に掲載した、下記のデータでやっているのですが 1行目も引数を与えて、絞り込むようなことはできますか? 1,1,1,1,2,2,2,2,3,3,3,3 "0405,0612","0613,0920","0921,1215","1216,0404","0409,0718","0719,1020","1021,0107","0108,0408","0321,0620","0621,0828","0829,0115","0116,0320" 1,2,3,4,1,2,3,4,1,2,3,4 度々、申し訳ありませんが宜しくお願いします。