ob1, ob2, 34 ob1, ob3, 56 ob1, ob4, 12 ob1, ob5, 78 ob1, ob6, 23 ob3, ob1, 56 ob7, ob1, 23 ob8, ob1, 12 ob9, ob1, 90 etc ...and what I need is to create a matrix like this
ob1 ob2 ob3 ob4 ob5 ob6 ob7 ob8 ob9
ob1 0 34 56 12 78 23 23 12 90
ob2 34
ob3 56
ob4 12
ob5 78
ob6 23
ob7 23
ob8 12
ob9 90
And for any 'duplicate results' like these
ob1, ob3, 56 ob3, ob1, 56Only take the first instance (as the result is the same, regardless of the direction).
#!/usr/local/bin/perl
use strict;
my $data = $ARGV[0];
# open file here
open(DATA, "$data") || die "cant open file for reading\n";
my %table;
my %rows;
my %cols;
for() {
my($row,$col,$val) = split ',';
$table{$row}{$col} = $val;
$rows{$row}++;
$cols{$col}++;
}
for my $col (sort keys %cols) {
print "\t$col";
}
print "\n";
for my $row (sort keys %rows) {
print "$row\t";
for my $col (sort keys %cols) {
print $table{$row}{$col} if defined $table{$row}{$col};
print "\t";
}
print "\n";
}
The results I get using the code above is:
ob1 ob2 ob3 ob4 ob5 ob6
ob1 34
56
12
78
23
ob3 56
ob7 23
ob8 12
ob9 90
Which isn't quite what I need, but I don't know how to fix it (due to my blind spot regarding hashes I suspect).
Fix the output? Or the matrix filling code?
One problem I see in the output code is that you don't treat missing values. Probably you should iterate over all objects.
my %all = ( %rows, %cols ) my @objs = keys %all;UPDATE: Another (or the?) problem I see is that you don't remove the newline in your data. chomp should fix this.
Have you investigated CPAN? Specifically, Text::Table? The trick becomes massaging your input data into the format that Text::Table wants it, but then it becomes much more trivial to get it printing right.
You were well on your way, but the first two on this list can confuse things enough that you can't see the rest. That's the way it happens, it's the things you're not looking at that get you.
use strict;
my %table;
my %rows_cols;
my %cols;
for() {
chomp;
my($row,$col,$val) = split ', *';
if ($row>$col) {
($row,$col) = ($col,$row);
}
$table{$row}{$col} = $val;
$rows_cols{$row}++;
$rows_cols{$col}++;
}
for my $col (sort keys %rows_cols) {
print "\t$col";
}
print "\n";
my $val;
for my $row (sort keys %rows_cols) {
print "$row\t";
for my $col (sort keys %rows_cols) {
if (defined $table{$row}{$col}) {
print $table{$row}{$col};
}
elsif (defined $table{$col}{$row}) {
print $table{$col}{$row};
}
else {
print "-";
}
print "\t";
}
print "\n";
}
__END__
ob1, ob2, 34
ob1, ob3, 56
ob1, ob4, 12
ob1, ob5, 78
ob1, ob6, 23
ob3, ob1, 56
ob7, ob1, 23
ob8, ob1, 12
ob9, ob1, 90
ob3, ob2, 87
prints
ob1 ob2 ob3 ob4 ob5 ob6 ob7 ob8 ob9
ob1 - 34 56 12 78 23 23 12 90
ob2 34 - 87 - - - - - -
ob3 56 87 - - - - - - -
ob4 12 - - - - - - - -
ob5 78 - - - - - - - -
ob6 23 - - - - - - - -
ob7 23 - - - - - - - -
ob8 12 - - - - - - - -
ob9 90 - - - - - - - -
Any reason why you couldn't update How to print list as matrix where there are already plenty of answers?
/J\
use strict;
use warnings;
my ($delim, $row, $col, $val, %matrix, %cols, @rows, @cols) = ' ';
while () {
chomp;
($row, $col, $val) = split /, /, $_;
$matrix{$row}{$col} = $val;
$cols{$col} = ();
}
@cols = sort keys %cols;
@rows = sort keys %matrix;
print join $delim, ' ', @cols;
for $row (@rows) {
print "\n", $row;
for $col (@cols) {
print $delim, $matrix{$row}{$col} ? sprintf('%3d', $matrix{$row}{$col}) : ' -';
}
}
__DATA__
ob1, ob2, 34
ob1, ob3, 56
ob1, ob4, 12
ob1, ob5, 78
ob1, ob6, 23
ob3, ob1, 56
ob7, ob1, 23
ob8, ob1, 12
ob9, ob1, 90
perlmonks.org content © perlmonks.org and Angharad, gellyfish, lima1, rodion, Tanktalus, TedPride
prlmnks.org © 2006 edmund von der burg (eccles & toad)
v 0.03