1

I'm new to perl, and I have trouble using a Cartesian Product. I already found the modules Set::CrossProd and Math::Cartesian::Product, but I can get them to work for my usage because I need to produce an array of.

What I exactly want to do is from a genetic sequence (of variable length, depend on the input), let use for example ARDN, i want all the possible output sequence of this. I say all because in fact, R means A or G, D means A, G or T and N mean A, T, C, or G.

So what i did, is have an hash of array for the different possible letters, then translate with a loop the input sequence into an Array of array. So in our example, I should get :

@AoA = (
["A"],
["A", "G"],
["A", "G", "T"],
["A", "T", "C", "G"],
);

however, it seems that I get an array of scalar, because when I print it, I have the letters that are displayed.

my code :

my %alphabet = (                  #not complete for simplification
    A => ["A"],
    D => ["A" , "G", "T"],
    N => ["A", "T", "C", "G"],
);

my @test = (
["A"],
["A" , "G", "T"],
["A", "T", "C", "G"],
);


my $seq = <STDIN>;
chomp $seq;
$seq =~ s// /g;
my @sequence = split(" ", $seq, length($seq));

my @AoA;
for (my $i = 0; $i < $#sequence; $i++) {
  push (@AoA, @{$alphabet{$sequence[$i]}});
};

print "@test";
print "@AoA";

Output :

ARDN
ARRAY(0x84ea30) ARRAY(0x867780) ARRAY(0x8677f8)
A A G A G T A T C G

What did I do wrong ? Thanks

3
  • When you want to see the detailed contents of any variable: use Data::Dumper; print Dumper($whatever_variable); Commented Dec 4, 2015 at 10:13
  • You can simplify your split as my @sequence = split //,$seq; Commented Dec 4, 2015 at 10:14
  • 1
    Your for loop is incorrect. $#array gives you the last index, not the size of the array, so you should use <=. But better yet, use for my $s (@sequence) instead, you'll have each member of @sequence in $s in the loop Commented Dec 4, 2015 at 10:15

2 Answers 2

3

In perl, an array cannot properly contain another array. Your push adds the elements of the second list to the array. You should be pushing references to arrays (and then adapt the rest of your code to expect references).

push (@AoA, \@{$alphabet{$sequence[$i]}});
Sign up to request clarification or add additional context in comments.

3 Comments

This worked, and now I'm able to do the cartesian product ! Thanks a lot !
Glad to hear it. Since your problem is resolved, please "accept" my answer by clicking on the big checkmark on the left.
Note that if the contents of %alphabet don't change, and you won't change them via AoA either, you can actually add a the reference directly: push @AoA,$alphabet{$sequence[$i]}. The code above will make a copy of the array rather than just point to it.
0

This looks like a perfect use case for map, which is great when you need to transform a list of things into a new list of things. The bulk of your code could be reduced to the following example, which, in my opinion, is more elegant and clear.

my $seq = <STDIN>;
chomp($seq);
my @AoA = map { $alphabet{uc($_)} } split(//, $seq);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.