One liner memo
また凝ってしまったので,メモ.
a 1 10 a 2 20 b 2 15 b 3 25 c 1 3 c 2 7 c 3 11 c 4 13
みたいに列,行,データと並ぶ入力から
,0,1,2,3,4 a,0,10,20,0,0 b,0,0,15,25,0 c,0,3,7,11,13
みたいな表を作る場合.
Excelとかでもできると思うんだけど,
やり方がわからないし,いろいろなデータ形式に対応するため,
One liner用の補助ツールを作ってみた.
# モジュール名がアレ何だけどね...
$ cat FN.pm package FN; use strict; use warnings; use base qw(Exporter); our @EXPORT = qw(convMat getV); sub getV(\%$$) { defined $_[0]->{$_[1]} ? $_[0]->{$_[1]} : $_[2] } sub convMatPrint($$%) { my($prop, $keys, %attr) = @_; my $def = getV %attr, "def", 0; my $shw = getV %attr, "shw", 3; my $sep = getV %attr, "sep", ","; my($t1, $t2) = ($,, $\); ($,, $\) = ($sep, "\n"); if(defined $prop->{"prev"}) { printf "%s%s", $prop->{"prev"}, $sep if($shw & 1); print map { getV %{$prop->{"cols"}}, $_, $def } @$keys; } elsif($shw & 2) { printf "%s", $sep if($shw & 1); print @$keys; } ($,, $\) = ($t1, $t2); } sub convMat(\%@) { my($prop, $keys, $row, $col, $val, %attr) = @_; if(!defined $prop->{"prev"} || $prop->{"prev"} ne $row) { convMatPrint($prop, $keys, %attr); $prop->{"prev"} = $row; $prop->{"cols"} = {}; } $prop->{"cols"}{$col} = $val; convMatPrint($prop, $keys, %attr) if(eof); } 1;
として,
$ perl -MFN -lane 'convMat %P,[0..4],@F[0..2]' <<EOF a 1 10 a 2 20 b 2 15 b 3 25 c 1 3 c 2 7 c 3 11 c 4 13 EOF ,0,1,2,3,4 a,0,10,20,0,0 b,0,0,15,25,0 c,0,3,7,11,13
となる.ただし,データはあらかじめソートしておく必要がある.
まあ,sortを通せばすむ話だけど.
一応オプションとしてセパレータsep,デフォルト値def,
ヘッダーなんかの表示を変えるshw(0123)を用意した.
結構使う頻度あったし,毎回コード書くの面倒なので作ってみたけど,
簡単に変換するツールとかあったのかな...
ExcelとかRならできそうな気がするんだけど,あんま詳しくないからな...