in reply to Capturing Non-Zero Elements, Counts and Indexes of Sparse Matrix

It is easy enough to manipulate matrices once you have the whole thing in memory (Math::Matrix), but i don't know if there is a clever way of reading by rows and calculating column scores on-the-fly like you want.

Here is one way of at least stripping out the non-zero elements, storing them column-wise and then joining them into one array and printing them out. I would have thought it would be easier to keep the values and indices (@Ai and @Ax) as array refs anyways, it would make it easier to reconstitute the matrix later one if you wanted to?

Anyways, here is my attempt at the problem, as usual, i am sure there are more elegant ways, but KISS always make more sense to me...

#! usr/bin/perl use strict; use warnings; use diagnostics; # 1. cumulative count of entries, as matrix is scanned columnwise. # Yielding: Ap = [ 0, 2, 5, 9, 10, 12 ]; # 2. row indices of entries, as matrix is scanned columnwise. # Yielding: Ai = [0, 1, 0, 2, 4, 1, 2, 3, 4, 2, 1, 4 ]; # 3. Non-zero matrix entries, as matrix is scanned columnwise. # Yielding: Ax = [2, 3, 3, -1, 4, 4, -3, 1, 2, 2, 6, 1]; my (@Ai, @Ax, @Ap,) = (); while (<DATA>) { chomp; my @elements = split /\s+/; ## process row-wise for (0 .. $#elements){ ## store non-zero elements by column if ($elements[$_] != 0){ ## store values by column push @{ $Ax[$_] }, $elements[$_]; ## store column index (minus one to make it start at zero) push @{ $Ai[$_] }, ($. -1); ## increment column totals ++$Ap[$_]; } } } ## make cumulative totals unshift @Ap, 0; for (1 .. $#Ap){ $Ap[$_] +=$Ap[$_-1]; } ## join array refs together @Ai = map{ @$_ } @Ai; @Ax = map{ @$_ } @Ax; print('@Ax = [', join(" ", @Ax), "]\n"); print('@Ai = [', join(" ", @Ai), "]\n"); print('@Ap = [', join(" ", @Ap), "]\n"); __DATA__ 2 3 0 0 0 3 0 4 0 6 0 -1 -3 2 0 0 0 1 0 0 0 4 2 0 1

Gives :

~ $ perl Desktop/test.pl @Ax = [2 3 3 -1 4 4 -3 1 2 2 6 1] @Ai = [0 1 0 2 4 1 2 3 4 2 1 4] @Ap = [0 2 5 9 10 12]

HTH

Just a something something...