Perlでニュースプログラムを作成する方法

このQ&Aのポイント
  • この記事では、Perlを使用してニュースプログラムを作成する方法について詳しく解説します。
  • データファイルから年度ごとの記事一覧を生成し、HTML形式で表示する方法や、記事の詳細ページを作成する方法について説明します。
  • また、年のインデックス(目次)を全ページに付ける方法についても解説します。
回答を見る
  • ベストアンサー

Perlでニュースプログラム

お世話になります。looserと申します。 Perlで、ニュースプログラムを作っているのですが、どうしてもやり方がわからなくて、教えていただきたいのです。 データファイルがあり、年度ごとの一覧をCGIからHTMLで出力し、また最初のページには、今年度の記事の一覧があり、それぞれの記事をクリックするとその記事の詳細が出てきます。 それぞれの記事には、全部の年の目次があって、その年の目次はクリックできないようにするというようなものを作りたいのです。 --data.csv-- 1,2002,記事1 2,2002,記事2 3,2003,記事3 4,2003,記事4 5,2003,記事5 6,2004,記事6 7,2005,記事7 -------プログラム--------- @data = &ReadData();#data.csvの読み込み #年一覧の配列の作成 foreach (@data){ ($no,$year) = split(/,/); unless($year == $last){push(@year_list,$year);} else{$last = $year;} } foreach $yr (@year_list){#年ごとのループ chomp($yr); foreach $data (@data){#データループ ($no,$year,$message) = split(/,/,$data); if($year == $yr){ # #この辺で配列格納?それともページ出力? # } } } -------------------------- これでやると、それぞれの年の一覧ページの出力が出来ないのです。 どなたか分かる方、また、サンプルになるスクリプトなどをご存知の方お願いいたします。 やりたい事 1.年度ごとの記事一覧の出力 2.記事ごとのページの出力 3.年のインデックス(目次)の出力→全ページに付く

  • Perl
  • 回答数1
  • ありがとう数0

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

  • ベストアンサー
  • taseki
  • ベストアンサー率66% (155/233)
回答No.1

> これでやると、それぞれの年の一覧ページの出力が出来ない の意味が、各年がそれぞれの記事数の分だけダブってしまう、という意味なら、以下の部分、 ----------------------- unless($year == $last){push(@year_list,$year);} else{$last = $year;} ----------------------- を、 ----------------------- unless($year == $last){push(@year_list,$year);} $last = $year; ----------------------- というように変えれば良いと思います。 前者では、ブレークフラグ $last の更新タイミングがおかしい、つまり、unless の else で $last を更新するのでは、「$year と $last が同じだったときに $last に $year を格納」という、意味のない処理になってしまいます。 なので、毎回 $last を更新するか、push に続けて、つまり $year と $last が異なったとき更新すればいいと思います。 蛇足ですが、unless は混乱しやすいので、なるべくなら「if ($year != $last)」と書いた方がいいとおもいます。 以上でとりあえず年ごとの表示は可能になりますが、もっと効率の良い方法としては、「年別の記事一覧」をあらかじめテーブルにしてしまえば、その後の処理で楽に引き出せるようになります。 具体的には、たとえば以下のように、 ----------------------- foreach (@data) { my ($doc_no, $year) = split(/,/); if ($doc_table{$year}) { push(@{$doc_table{$year}}, $doc_no); } else { $doc_table{$year} = [$doc_no]; } } ----------------------- こうしておくと、たとえば2002年の記事が欲しければ、 @{$doc_table{'2002'}} という配列にすべて入っています。 一覧にするなら、たとえば以下の感じ。 ----------------------- foreach (sort keys(%doc_table)) { print "$_ 年の記事は " . scalar(@{$doc_table{$_}}) . " 件あります。\n"; foreach (@{$doc_table{$_}}) { print "No. $_\n"; } print "-----\n"; } ----------------------- さらにもっと進化させるなら、記事ごとの全データをまとめてハッシュのハッシュにしておけば、特定の記事が欲しい場合に、すぐに参照できます。 前述の「年別の記事一覧」と同時に作成するなら、たとえば以下のように。 ----------------------- foreach (@data) { my ($doc_no, $year, $text) = split(/,/); if ($doc_table{$year}) { push(@{$doc_table{$year}}, $doc_no); } else { $doc_table{$year} = [$doc_no]; } # ★ これを追加 ↓ $doc{$doc_no} = {year => $year, text => $text}; } ----------------------- 年と記事内容だけでなく著者や画像などもあれば、同様に追加。 こうしておくと、たとえば記事NO.5の「年」が欲しければ、 $doc{'5'}{'year'} で、あるいは記事NO.3の「記事内容」が欲しければ、 $doc{'3'}{'text'} というように参照できます。 先ほどの一覧を、これで表現すると、 ----------------------- foreach (sort keys(%doc_table)) { print "$_ 年の記事は " . scalar(@{$doc_table{$_}}) . " 件あります。\n"; foreach (@{$doc_table{$_}}) { print "No. $_ - " . $doc{$_}{'year'} . '年 - ' . $doc{$_}{'text'} . "\n"; } print "-----\n"; } ----------------------- これで、ご希望の各表示が可能と思います。

関連するQ&A

  • perlでの三次元配列の作り方

    perlで三次元配列をテキスト入力から作りたいのですが、例えば二次元配列の場合 foreach $line (@input) push @data, [split /[:]/, $line]; で@dataが二次元配列になるのですが、三次元配列の場合このあとに push @output, \@data; とするとリファレンスが同じであるためループをまわしてもうまく三次元になりませんよね。 解決法はありますでしょうか?

  • Perlの初歩的な質問・・・

    @data に大量のデータが格納されていると仮定して、次のようにループ処理するとします・・・ for($i = 0 ; $i < @data ; ++$i){ @XXX = split(/\t/, $data[$i]); } このように @data のデータをさらに細かく配列化して @XXX に代入したいのですが、ループのたびに @XXX の名前を XXX0 , XXX1 , XXX2..... とするには、どうしたらよいのでしょうか。

    • ベストアンサー
    • Perl
  • Perl/配列のループに関して教えてください。

    my @shop = [ {'start_hour'=> '1100','shift'=> [1,2] }, {'start_hour'=> '1130','shift'=> [1,3] } ] という配列があってそれをループで回したいのですが、 ▼以下だとNG foreach my $data (@shop){print $data->{start_hour};} ▼以下だと最初の1つだけOK foreach my $data (@shop){print $data->[0]->{start_hour};} という状況です。なぜ$data->{start_hour};で取得できないのでしょうか? 助けて頂けるとうれしいです★

    • ベストアンサー
    • Perl
  • perl初心者ですが、プログラム作成で行き詰ってしまいました。

    perl初心者ですが、プログラム作成で行き詰ってしまいました。 参考書を読みあさり、色々とググってみたのですが、どうしても組み立てられません。知識のある方ご回答よろしくお願いします。 一つ目は: 英語の文章を記憶したファイルを指定し,その内容を読み込み,文章内に含まれる単語を出現頻度の降順で表示させるプログラムを作成すること 「1位:・・・(・・回)」 「2位:・・・(・・回)」 ... なお,一つの単語が二行にまたがることはないものとする。 二つ目は: テストの成績データを記憶したCSV ファイルを指定し,その内容を読み込み,各学生の総合点と順位,各科目の最高点,最低点,平均点を記憶したCSVファイルを書き出すプログラムを作成せよ。 なお,入力用のファイルと出力用のファイルはキーボード入力で指定するものとする。 また,異なる学生数および科目数のCSV ファイルを読み込んでも正しく動作するようにすること。 卒業のかかったレポートで、この二つを完成させないと先に進めないのです。 本当に図々しい質問で大変申し訳ありません。知識のある方どうかご教授ねがいます。 *ひとつめに関しては: open (FILE, 'perl.txt') or die "$!"; while (my @array = <FILE>){ foreach (@array) { $count{ $_ }++ ; } @rank = sort { $count{ $b } <=> $count{ $a } } keys %count ; foreach (0..$#rank) { $kagi = $rank[ $_ ]; $kaisu = $count{ $kagi } ; print $_+1, "位:$kagi($kaisu 回)\n" ; } } のように書いたところで行き詰ってしまいました。 二つ目は: open (FILE, 'data.txt') chomp(@data = <FILE>) ; $i= 1 ; # 行番号を記憶する変数 for (@data) { # 各行に対して以下を繰り返す. # 各行の数値を配列の要素として記憶する. @list = split(/,/, $_) ; # サブルーチンを呼び出して,結果を表示 print "$i行目:" ; print "数値:",&cardinality(@list),"個," ; print "最大値:",&maximum(@list),"," ; print "最少値:",&minimum(@list),"," ; print "合計:",&summation(@list),"," ; print "平均:",&average(@list),"\n" ; # 行番号の更新 $i++ ; } とまで書き、もう何が何だか訳わからなくなってしまいました。

    • ベストアンサー
    • Perl
  • csv出力した内容を配列で取得できますか?

    データベースのテーブル内容をサーバー上にcsv出力すると同時に出力した内容を配列で取得できないでしょうか?(PDOを利用しています) $sql= "SELECT id, name FROM tb INTO OUTFILE '/tmp.csv'"; $stmt = $dbh->query($sql); これでcsvは出力されるのですが、csv出力した内容を配列で取得したく、 $array = $stmt->fetchAll(PDO::FETCH_ASSOC); をするとGeneral Errorとなります。 先にSELECTで内容を配列で取得してから配列のループでcsvの内容を作成し、出力する方法もありますが、データ量が数十万件あるのでループ処理が遅い気がしています。 良い方法があればお教えください。 よろしくお願い致します。

    • ベストアンサー
    • MySQL
  • foreachの使い方

    foreach (split(/<br>/i,$text)){ #処理 } 今までこのようにforeachでループさせていたのですがxhtml形式に順次対応させていこうと改変中です <br>も旧データの中に残った状態なので、<br>と<br />の両方でループするようにしたいのですが、どう書けばいいでしょうか foreach ((split(/<br>/i,$text)) || (split(/<br />/i,$text))){ #処理 } これじゃあまずいですよね? 本来ならトライ&エラーあるのみですが、ループの中が複雑な上にいろんなところに散らばっているデータの書き換えもしてしまうのでテスト用に改変することも大変で、トライ&エラーをやるにも難しい状況なのでここはどうしても一発目で成功させたいのです。

    • ベストアンサー
    • Perl
  • 日付データを比較して出力したい!

    いつもお世話になります。 2つの日付を比較して、月の差を求めて、 for文でその月差分を1つめの変数に出力したいのですが、 うまくいきません。XAMPP環境です。 自分でも調べてみますが、お願いします。 ------------------------------ <?php //2007年9月と2007年12月を比較 $date1="2007-09"; $date2="2007-12"; //差分を求める list($year1,$month1) = split('[/.-]', $date1); list($year2,$month2) = split('[/.-]', $date2); $year=$year2-$year1; $month=$month2+1-$month1; $total_month=$year*12+$month; //for文で出力 for($k=0;$k<$total_month;$k++){ echo $k."回目のループ。<BR>"; echo $k+$date1; } ?> ----------------------------------- --------実行結果-------- 0回目のループ。 2008 1回目のループ。 2009 2回目のループ。 2010 3回目のループ。 2011 ------------------------ となってしまいます。求めたい処理は --------理想結果-------- 0回目のループ。 2007/09 1回目のループ。 2007/10 2回目のループ。 2007/11 3回目のループ。 2007/12 ------------------------ です。よろしくお願いしますm(_ _)M

    • ベストアンサー
    • PHP
  • PHPでCSVファイルから行指定してループする方法

    こんにちは。 PHPでループ処理をしているのですが、ふと疑問にあたりました。 CSVファイルをオープンしそれを一行づつ読み込みたいのです。 「次のページ」などのよくある方法のように30行あったら次のページをクリック。 次ページでは31行目から60行目までを表示、その繰り返しのようなループを考えています。 Perlの場合foreach(1 .. 30){} のように配列の始点終点の指定ができたとおもうのですが、PHPでもこのような処理は可能なのでしょうか? 恐れ入りますがご教授お願いします。

    • ベストアンサー
    • PHP
  • <Perl>参照配列の出力に失敗する。

    <Perl>参照配列の出力に失敗する。 お世話になります。 配列の出力部で以下のエラーが出力されます。 Use of uninitialized value in print at test2.pl line 12. -----コーディングは以下の通りです。----- #!C:\perl use strict; use warnings; my @l = (); #----------- #GetDataへCSVファイル名と、格納用配列を渡す #----------- my $cnt = &GetData("test.csv", \@l); print "COUNT -> ".$cnt; for(my $i=0; $i < $cnt; $i++){ print $l[$i]; } ################################################################## # 概   要:指定したCSVファイルをオープンしCSVデータを配列に取得する。 # パラメータ:ファイル名, CSVデータ格納用配列 # 戻 り 値:データ取得件数 ################################################################## sub GetData { my ($f, @bf) = @_; my $rcnt = 0; print "FILE NAME -> ".$f."\n"; if ( open(FP, "<${f}") ){ print "FILE OPEN -> success.\n"; @bf = split(/,/, <FP>); close(FP); $rcnt = @bf; print "CSV GET COUNT -> ".$rcnt."\n"; } return $rcnt; } -----実行結果は以下の通りです。----- D:\>perl test.pl FILE NAME -> test.csv FILE OPEN -> success. CSV GET COUNT -> 5 Use of uninitialized value in print at test2.pl line 12. Use of uninitialized value in print at test2.pl line 12. Use of uninitialized value in print at test2.pl line 12. Use of uninitialized value in print at test2.pl line 12. COUNT -> 5 -----CSVファイルの内容は以下の通りです。(ファイル名:test.csv)----- あいうえお,かきくけこ,さしすせそ,たちつてと,なにぬねの 配列の要素数が取れているので、配列内にデータは格納されているとは思っています。 出力方法をどのように正せばよいがご教示お願い致します。

    • ベストアンサー
    • Perl
  • ソートの方法

    某CGIを改造中です。 記事を更新日順でソートしなおしたいです。 多分、ソート部分だと思われる部分の現状は、 ----- foreach (@data) {   ($no,$year1,$month1,$day1,$name~~) = split(/<>/);   @tmp = ();   @tmp = map {(split /<>/)[0]} @data;   @data = @data[sort {$tmp[$b] cmp $tmp[$a]} 0 .. $#tmp]; } ----- です。 ただ、見ての通り、日付が「$year1,$month1,$day1」と分かれています。これを結合して(20060309のような形)、それを元にソートしなおしたいのですが、どのようにしたら良いでしょうか? 方法を教えてください。お願いします。

    • ベストアンサー
    • Perl

専門家に質問してみよう