Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

looping through an array reference of hash reference

by PrincePerl (Novice)
on Oct 26, 2011 at 02:53 UTC ( [id://933775]=perlquestion: print w/replies, xml ) Need Help??

PrincePerl has asked for the wisdom of the Perl Monks concerning the following question:

Hello all..Im working on a cgi script am trying to compare 2 data files, but i have to have them as Array reference of hash references so i can pass the results on to an html template. Im still working on the code, i just thought i'll get another insight. Thanks in advance i have updated the code, but now i am getting an "Use of uninitialized value in string eq"

my code

#!/usr/bin/perl -w use strict; use CGI; use HTML::Template; my $cgi = new CGI; my $tmpl = HTML::Template->new (filename => 'tmpl/annotation.tmpl'); print "Content-type: text/html\n\n"; my $offgenes = 0; my $prodgenes = 0; my @offcordinates; my @prodcordinates; my $exactmatching = 0; my $start; my $stop; my $start1; my $stop1; my $threeprimematch; my %findgene; my %findgene2; my @officialannotation = (); my @prodigalannotation = (); my $hash_ref; my $hash_ref2; open(INFILE, "<", "genbankfile.txt") or die "cannot open file $!"; while(<INFILE>) { if ($_ =~ /\d+/) { $offgenes++; } @offcordinates = split; $findgene = { "start" => $offcordinates[1], "stop" => $offcordinates +[0] }; push @officialannotation, $findgene; } open(INFILE2, "<", "prodigalAnnotation.txt") or die "cannot open file +$!"; while(<INFILE2>) { if($_ =~ /\d+/) { $prodgenes++; } @prodcordinates = split; $findgene2 = { "start1" => $prodcordinates[0], "stop1" => $prodco +rdinates[1] }; push @prodigalannotation, $findgene2; } foreach $genes ( @officialannotation ) { my %genes_= %$genes; foreach $genes2 ( @prodigalannotation ) { my %genes2 = %$genes2; if($genes{start} eq $genes2{start1}) { $exactmatching++; } } } print "$offgenes\n"; print "$prodgenes\n"; print "$exactmatching\n"; close(INFILE); close(INFILE2);

Data file 1 data file 2

start stop start stop

1234 5678 1234 5678

2123 1234 3233 2123

I am trying to loop though to compare the data in file 1 to file 2.

for example if 1234 and 5678 is seen in the start and stop column in file 1 and seen in file 2, count that line.

Also, if 2123 is seen is the start column and not seen in the start of the second file 1. count that also. This is my biggest problem at the moment. help

Replies are listed 'Best First'.
Re: looping through an array reference of hash reference
by jwkrahn (Abbot) on Oct 26, 2011 at 03:25 UTC
    my @officialannotation = []; my @prodigalannotation = [];

    Why are you assigning an array reference to $officialannotation[0] and $prodigalannotation[0]?



    %findgene = ( "start" => $offcordinates[1], "stop" => $offcordinates +[0] ); $hash_ref = \%findgene;

    Or just:

    $hash_ref = { "start" => $offcordinates[1], "stop" => $offcordinates[ +0] };


    @officialannotation = []; push @officialannotation, $hash_ref;

    You are removing all previous elements of @officialannotation with the assignment, and you could just write that as:

    @officialannotation = ( [], $hash_ref );

    But why do you need the array reference as the first element?    And because both %findgene and $hash_ref are at file scope the hash reference will always point to the same variable.



    for $hash_ref ( @$officialannotation ) { while (my $start, $stop) = each %$hash_ref ) { for $hash_ref2 ( @$prodigalannotation) { while (my $start1, $stop2) = each %$hash_ref2 ) {

    Because the first element of @officialannotation and @prodigalannotation are ARRAY references instead of HASH references you should be getting error messages here.



Re: looping through an array reference of hash reference
by NetWallah (Canon) on Oct 26, 2011 at 04:42 UTC
    Here is somewhat simplified, but untested code , in an attempt to steer you toward more idiomatic code:
    my @officialannotation = (); # An empty list. NOT [] , which is an emp +ty array-ref my $offgenes; open(my $infile , "<", "genbankfile.txt") or die "cannot open file gen +bankfile.txt $!"; while(<$infile>) { $offgenes++ if ($_ =~ /\d+/) ; my ($start, $stop) = split; push @officialannotation, {start=> $start, stop => $stop}; } close $infile; #.. collect the other one in the same way # Then compare the 2 arrays of hashrefs : for my $p (@prodigalannotation){ next unless my ($candidate) = grep {$p->{start} eq $_->{start}} @of +ficialannotation; $exactmatching++ if $candidate->{stop} eq $p->{stop}; }
    Note - there are many assumptions of the data, and no error checking, and inefficiencies, so this code is far from ideal, but I offer it as an incremental improvement on the OP.

                "XML is like violence: if it doesn't solve your problem, use more."

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://933775]
Approved by moritz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (10)
As of 2024-04-23 14:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found