Pergunta

I have an input file like so, separated by newline characters.

AAA
BBB
BBA

What would be the most efficient way to count the columns (vertically), first with first, second with second etc etc.

Sample OUTPUT:

ABB 
ABB 
ABA

I have been using the following, but am unable to figure out how to remove the scalar context from it. Any hints are appreciated:

while (<@seq_prot>){
    chomp; 
    my @sequence = map substr (@seq_prot, 1, 1), $start .. $end;
    @sequence = split;
}

My idea was to use the substring to get the first letter of the input (A in this case), and it would cycle for all the other letters (The second A and B). Then I would increment the cycle number + 1 so as to get the next line, until I reached the end. Of course I can't seem to get the first part going, so any help is greatly appreciated, am stumped on this one.

Foi útil?

Solução 2

You'll have to read in the file once for each column, or store the information and go through the data structure later.

I was originally thinking in terms of arrays of arrays, but I don't want to get into References.

I'm going to make the assumption that each line is the same length. Makes it simpler that way. We can use split to split your line into individual letters:

my = $line = "ABC"
my @split_line = split //, $line;

This will give us:

$split_line[0] = "A";
$split_line[1] = "B";
$split_line[2] = "C";

What if we now took each letter, and placed it into a @vertical_array.

my @vertical_array;
for my $index ( 0..@#split_line ) {
   $vertical_array[$index] .= "$split_line[$index];
}

Now let's do this with the next line:

$line = "123";
@split_line = split //, $line;
for my $index ( 0..@#split_line ) {
   $vertical_array[$index] .= "$split_line[$index];
}

This will give us:

$vertical_array[0] = "A1";
$vertical_array[1] = "B2";
$vertical_array[2] = "C3";

As you can see, I'm building the $vertical_array with each interation:

use strict;
use warnings;
use autodie;
use feature qw(say);

my @vertical_array;
while ( my $line = <DATA> ) {
    chomp $line;
    my @split_line = split //, $line;
    for my $index ( 0..$#split_line )  {
        $vertical_array[$index] .= $split_line[$index];
    }
}

#
# Print out your vertical lines
#
for my $line ( @vertical_array ) {
    say $line;
}

__DATA__
ABC
123
XYZ
BOY
FOO
BAR

This prints out:

A1XBFB
B2YOOA
C3ZYOR

If I had used references, I could probably have built an array of arrays and then flipped it. That's probably more efficient, but more complex. However, that may be better at handling lines of different lengths.

Outras dicas

Basically, you're trying to transpose an array.

This can be done easily using Array::Transpose

use warnings;
use strict;

use Array::Transpose;

die "Usage: $0 filename\n" if @ARGV != 1;

for (transpose([map {chomp; [split //]} <>])) {
    print join("", map {$_ // " "} @$_), "\n" 
}

For an input file:

ABCDEFGHIJKLMNOPQRS
12345678901234
abcdefghijklmnopq
ZYX

Will output:

A1aZ
B2bY
C3cX
D4d
E5e
F6f
G7g
H8h
I9i
J0j
K1k
L2l
M3m
N4n
O o
P p
Q q
R
S
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top