Что-то вроде этого может быть?
use warnings;
use strict;
my @data = (
{ name => 'Foo', funcs => [qw/abc def ghi xyz/] },
{ name => 'Bar', funcs => [qw/def jkl mno uvw xyz/] },
{ name => 'Baz', funcs => [qw/abc uvw xyz/] },
);
my %allfuncs = ( map { map {$_=>undef} @{$$_{funcs}} } @data );
$$_{funcs} = { %allfuncs, map {$_=>1} @{$$_{funcs}} } for @data;
use Data::Dump;
dd @data;
# just for output:
use List::Util qw/max/;
my $maxlen = max map {length} map({$$_{name}} @data), keys(%allfuncs);
my $fmt = join(' ', ("%${maxlen}s") x @data)."\n";
printf $fmt, map { $$_{name} } @data;
for my $f (sort keys %allfuncs) {
printf $fmt, map { $$_{funcs}{$f}?$f:'' } @data;
}
Выход:
(
{
funcs => { abc => 1, def => 1, ghi => 1, jkl => undef, mno => undef, uvw => undef, xyz => 1 },
name => "Foo",
},
{
funcs => { abc => undef, def => 1, ghi => undef, jkl => 1, mno => 1, uvw => 1, xyz => 1 },
name => "Bar",
},
{
funcs => { abc => 1, def => undef, ghi => undef, jkl => undef, mno => undef, uvw => 1, xyz => 1 },
name => "Baz",
},
)
Foo Bar Baz
abc abc
def def
ghi
jkl
mno
uvw uvw
xyz xyz xyz
Обновление: Если ваши входные данные поступают в виде AoA, это займет @table
и даст тот же @data
, что и выше (в основном это транспонирует AoA, а затем создает хеш-структуру) :
my @table = ( [qw/Foo Bar Baz/], [qw/abc def abc/], [qw/def jkl uvw/],
[qw/ghi mno xyz/], [qw/xyz uvw/], [undef, qw/xyz/] );
my @data;
for my $col ( 0 .. $table[0]->$#* )
{ push @data, [ map {$_->[$col]//()} @table ] }
@data = map { {name=>shift @$_, funcs=>$_} } @data;
А если вам нужен выходной формат для AoA:
my @out = ( [map {$$_{name}} @data] );
for my $f (sort keys %allfuncs)
{ push @out, [ map {$$_{funcs}{$f}?$f:undef} @data ] }
Производит @out
:
(
["Foo", "Bar", "Baz"],
["abc", undef, "abc"],
["def", "def", undef],
["ghi", undef, undef],
[undef, "jkl", undef],
[undef, "mno", undef],
[undef, "uvw", "uvw"],
["xyz", "xyz", "xyz"],
)