http://qs1969.pair.com?node_id=622077

gasho has asked for the wisdom of the Perl Monks concerning the following question:

Dear Perl Monks. I have collected bunch of arrays that first element of each array should be a key I would like to produce print out like bellow. Do you have more elegant solution ? I will appreciate
```ArrA = qw(A 1 2 3 4 5);
ArrB = qw(B 1 2 5 6);
ArrC = qw(C 2 3);

for (\$i=1; \$i < 6; \$i++) {

push(@{\$CAPABILITIES{\$ArrA[\$i]}}, \$ArrA[0]);
push(@{\$CAPABILITIES{\$ArrB[\$i]}}, \$ArrB[0]);
push(@{\$CAPABILITIES{\$ArrC[\$i]}}, \$ArrC[0]);

}

foreach \$key (sort (keys %CAPABILITIES)) {
print "\$key => ";
foreach \$role (sort @{\$CAPABILITIES{\$key}}) {
print "\$role ";
}
print "\n";
}

# Desired Printout
=begin COMMENT

Key/Value
======================
1 =>        A   B
2 =>        A   B   C
3 =>        A   C
4 =>        A
5 =>        A   B
6 =>        B

OR

Key/Value   A   B   C
======================
1           X   X
2           X   X   X
3           X       X
4           X
5           X   X
6               X

=end COMMENT
=cut
(: Life is short enjoy it :)

Replies are listed 'Best First'.
Re: Multiple arrays in a hash
by ikegami (Patriarch) on Jun 19, 2007 at 19:34 UTC

What you called "CABABILITIES", I called "roles" for short.
That which has "CABABILITIES", I called "actor".

Instead of building a hash of roles by actor, build a hash of actors by role. That way, your data structure will ressemble your output. (Update: Oops, that is what you are doing. The rest of the post applies, though.)

In the code below, I replaced doing the same thing to three different arrays with a single loop.

```use strict;
use warnings;

my @arrays = (
[ qw( A 1 2 3 4 5 ) ],
[ qw( B 1 2 5 6   ) ],
[ qw( C 2 3       ) ],
);

my %actors_by_role;
foreach my \$array (@arrays) {
my (\$actor, @roles) = @\$array;
foreach my \$role (@roles) {
push @{\$actors_by_role{\$role}}, \$actor;
}
}

my @roles = sort keys %actors_by_role;

foreach my \$role (@roles) {
print(join("\t", \$role => sort @{\$actors_by_role{\$role}}), "\n");
}

Output:

```1       A       B
2       A       B       C
3       A       C
4       A
5       A       B
6       B

From there, it's not hard to get the second output.

```use strict;
use warnings;

my @arrays = (
[ qw( A 1 2 3 4 5 ) ],
[ qw( B 1 2 5 6   ) ],
[ qw( C 2 3       ) ],
);

my %actors;
my %actors_by_role;

foreach my \$array (@arrays) {
my @roles = @\$array;
my \$actor = shift(@roles);

\$actors{\$actor} = 1;

foreach my \$role (@roles) {
\$actors_by_role{\$role}{\$actor} = 1;
}
}

my @roles  = sort keys %actors_by_role;
my @actors = sort keys %actors;

{
foreach my \$actor (@actors) {
print("\t", \$actor);
}
print("\n");
}

foreach my \$role (@roles) {
print(\$role);
foreach my \$actor (@actors) {
print("\t", \$actors_by_role{\$role}{\$actor} ? 'X' : ' ');
}
print("\n");
}
```        A       B       C