I believe this has passed its first test. Output, then source, just one code tag, buyer beware:
$ ./3.rm.pl ["abcdef", "abcdefg", "abcde", " bcdefgh", " bcd "] [ ["a" .. "f"], ["a" .. "f"], ["a" .. "e", " "], [" ", "b" .. "f"], ] inside first anonymous block ok 1 exiting first anonymous block 1..1 $ cat 3.rm.pl #!/usr/bin/perl -w use 5.011; use Data::Dump; my $input = <<'(END INPUT)'; abcdef abcdefg abcde bcdefgh bcd (END INPUT) $input=~ s/\t/ /g; my @lines = split /\n/, $input; dd \@lines; my $out = make_rectangular( \@lines, 4, 6 ); $out = [ map { [split //] } @$out ]; #convert reference dd $out; use Test::More; { say "inside first anonymous block"; my $subset = getsubset( $out, "R1" ); is_deeply $subset, [ [ 'a' .. 'f' ] ]; say "exiting first anonymous block"; } done_testing(); sub make_rectangular { my ( $lines, $maxrows, $maxlength ) = @_; my @out; my $rowcount=1; for my $line (@$lines) { my $trimmed = substr $line, 0, $maxlength; push @out, sprintf "%-*s", $maxlength, $trimmed; last if ++$rowcount>$maxrows; } return \@out; } sub rangeparse { use Carp; local $_ = shift; my @o; # [ row1,col1, row2,col2 ] (-1 = last row/col) if ( @o = /\AR([0-9]+|n)C([0-9]+|n):R([0-9]+|n)C([0-9]+|n)\z/ ) { } elsif (/\AR([0-9]+|n):R([0-9]+|n)\z/) { @o = ( $1, 1, $2, -1 ) } elsif (/\AC([0-9]+|n):C([0-9]+|n)\z/) { @o = ( 1, $1, -1, $2 ) } elsif (/\AR([0-9]+|n)C([0-9]+|n)\z/) { @o = ( $1, $2, $1, $2 ) } elsif (/\AR([0-9]+|n)\z/) { @o = ( $1, 1, $1, -1 ) } elsif (/\AC([0-9]+|n)\z/) { @o = ( 1, $1, -1, $1 ) } else { croak "failed to parse '$_'" } $_ eq 'n' and $_ = -1 for @o; return \@o; } sub getsubset { use Carp; my ( $data, $range ) = @_; my $cols = @{ $$data[0] }; @$_ == $cols or croak "data not rectangular" for @$data; $range = rangeparse($range) unless ref $range eq 'ARRAY'; @$range == 4 or croak "bad size of range"; my @max = ( 0 + @$data, $cols ) x 2; for my $i ( 0 .. 3 ) { $$range[$i] = $max[$i] if $$range[$i] < 0; croak "index $i out of range" if $$range[$i] < 1 || $$range[$i] > $max[$i]; } croak "bad rows $$range[0]-$$range[2]" if $$range[0] > $$range[2]; croak "bad cols $$range[1]-$$range[3]" if $$range[1] > $$range[3]; my @cis = $$range[1] - 1 .. $$range[3] - 1; return [ map { sub { \@_ } ->( @{ $$data[$_] }[@cis] ) } $$range[0] - 1 .. $$range[2] - 1 ]; } __END__ $
Copy that, so, yahoo, right? I'll write a few more tests....
In reply to Re^4: rectangularizing input to become array
by Aldebaran
in thread rectangularizing input to become array
by Aldebaran
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |