プログラマでありたい

おっさんになっても、プログラマでありつづけたい

Perlで2次元ハッシュ(の一歩手前)

 下記のようなデータを、日付別でみたいなぁと思いました。
いわゆる、クロス集計です。


元データ

20090301 breakfast 400
20090301 lunch 1000
20090301 dinner 800
20090302 breakfast 700
20090302 lunch 500
20090302 dinner 4000
20090303 breakfast 800
20090303 dinner 900
20090303 lunch 1000

1カラム目が、日付
2カラム目が、カテゴリー
3カラム目が、バリューです
出したいカテゴリーは決まっているのですが、その日にカテゴリーデータが存在しているかは保証なしです。
※カテゴリーとバリューの値は、適当につくりました。


期待データ

date,breakfast,lunch,dinner
20090301,400,1000,800
20090302,700,500,4000
20090303,800,1000,900


 テンポラリーで使いたかっただけなので、動けばなんでもよいという感じでどういう選択肢があるかなと考えました。
1.Excelでマクロを組む
2.perlとshellを組み合わせる
3.SQLにぶっこむ


面倒くさかったので、2で行いました。2次元ハッシュにしたら楽勝じゃないと思ってたんですが、使い方忘れてました。。。ので備忘録。

#!/usr/bin/perl

use strict;
use warnings;
use Data::Dumper;

my $date="";
my %hash;
while (<>) {
  my ($date,$category,$num) = split(/ /,$_);
  chomp($num);
  $hash{$date}->{$category} = $num;
}

print "date,breakfast,lunch,dinner\n";
while (my ($key,$val) = (each %hash)) {
  print $key;
  print ",$val->{'breakfast'}";
  print ",$val->{'lunch'}";
  print ",$val->{'dinner'}";
  print "\n";
}
#print Dumper(%hash);

 ポイントは、Data::Dumperを使って中身確認しながらやれよと言うところくらいですかね。本当に2次元的に使うならば、$valを元にもう一度展開ですね。その際の参照が、%$valになる所が注意ですかね。あとハッシュなので並び順が保証されていないので注意。
 うーん。物忘れの酷さが深刻になってきました。