• ベストアンサー

perlで重複データを集計

aaaaaa,10 bbbbbb,8 cccccc,3 bbbbbb,2 aaaaaa,1 このようなデータをHTMLフォームから取り込み aaaaaa,11 bbbbbb,10 cccccc,3 と、同じデータの合計値を出すシンプルな方法を教えてください。 CSVからの読み込みではなくフォームからのデータになります。

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

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

CSVというのはCSVファイルと予想しますが、ファイルからとフォームからでそんなに違わないと思うのですが。 ファイルは簡単に行ごとにわかれた配列として読み込むことができますよね。 フォームからデータを受け取って、行ごとの配列にするのもsplitを使えば簡単でしょう。 そうすると、行ごとの配列を受け取って集計するサブルーチンを作ればどちらにも使えると思いませんか? あとは#1さんのおっしゃるとおりやると良いでしょう。 連想配列だけでやると整列して出てこないので、ちょっと工夫が必要です。 というわけで、ちょっと書いてみました。 use strict; sub aggregate { my $csvp = shift; my @csv = @$csvp; my %subtotal; my @order; foreach (@csv) { chomp; my ($id, $num) = split(/,/); if (!exists $subtotal{$id}) { push(@order, $id); } $subtotal{$id} += $num; } my $ret = ""; foreach my $key (@order) { my $value = $subtotal{$key}; $ret .= "$key,$value\n"; } return $ret; } use CGI; my $q = new CGI; my $csv = $q->param('csv'); if ($csv) { my @csv_array = split('\n', $csv); print $q->header('text/plain'); print &aggregate(\@csv_array); } else { print $q->header; print $q->start_html; print $q->start_form(-action=>$q->url, -method=>'post'); print $q->textarea(-name=>'csv'); print $q->submit; print $q->end_form; print $q->end_html; } まず、まじめにCSVを解釈するつもりがなかったのでCSVの値には英数字しか来ないと持っています。本気でCSVを解釈するなら、"の取り扱いを真面目にやる必要があるでしょう。あるいは、Text::CSVなどのモジュールを使ったほうが良いかもしれません。 ちなみに、このプログラムでは入力で出てきた順序を保って出力するようにしています。 例えば、 a,1 c,2 b,3 c,3 と入力すると、 a,1 c,5 b,3 と出します。 先に述べたように、aggregateサブルーチンに与えるデータは行ごとに分けて配列に入れたものであれば良いので、ファイルの場合はもっと単純なコードで使うことができます。 open(my $f, "example.csv"); my @c = <$f>; close($f); print &aggregate(\@c); 実際に使う場合はtext/plainでの出力ではなくpreあたりで出力して、下にフォームを表示するくらいしないと不便だと思いますが、そこは自分でやってみてください。

すると、全ての回答が全文表示されます。

その他の回答 (1)

  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.1

私だったら %total みたいなハッシュに ($k,$v) = split(/,/) とかして $total{$k} += $v ; で足していきます。

すると、全ての回答が全文表示されます。

関連するQ&A