Iarwain
Iarwain

Reputation: 199

Perl: Combining array elements with hashmap values

I'm trying to paste two values together in a string. One value is an array element and the other a hashmapvalue. But I keep having this error:

Use of uninitialized value in concatenation (.) or string
  at makeNewCSV.pl line 104, <$fh> line 2020.

This is my code:

use feature qq(say);

my @nodeIdArray;
my @sequenceArray;
my @completeLineArray;

my %fastaHash = ();

[...]

sub readCsv{#Reads the CSV and puts all the Node ID's in an array

my ($file) = @_;
my $nodeID = qr{\d+\,(\d+)};

open(my $fh, '<', $file) or die "Error while reading CSV: $!";

    while(my $line = <$fh>){

        if($line =~ $nodeID){

            push(@nodeIdArray, $1);
        }
    }

close($fh);

searchFasta();
}


sub searchFasta{#Reads and searches the fasta file for contigs with a matching node ID

my ($file) = $ARGV[1];
my $fastaNodeID = qr{>NODE_(\d+)_LENGTH_\d+_COV_[\d.]+\n([ACTGN\n]+)};
my @matches;


open(my $fh, '<', $file) or die "Error while reading fasta: $!";

    my @allLines = <$fh>;

    my $makeString = join('', @allLines);
    my $lineAsString = uc($makeString);

    while($lineAsString =~ m/$fastaNodeID/g){

        my $node_ID = $1;
        my $sequence = $2;

        $sequence =~ s/\n//;

        $fastaHash{$node_ID} = $sequence;
    }

close($fh);


pasteLines();
}

sub pasteLines{

my $fullLine = "";
my $file = $ARGV[0];
my @hashKeys = keys(%fastaHash);
my $index = 0;
my $numberOfRepeat = 0;

open(my $fh, '<', $file) or die "Error while reading CSV (2): $!";


    my @allLines = <$fh>;
    my $arrayLength = @allLines;

    foreach my $line(@allLines){

        chomp($line);
    }

    while($numberOfRepeat <= $arrayLength){     

        foreach my $key(@hashKeys){

            if($key = $nodeIdArray[$index]){


                no warnings qw(uninitialized);  #DEBUG:
                say qq(DEBUG: \$fastaHash{$key} = "$fastaHash{$key}");
                say qq(DEBUG: \$fullLine = $allLines[$index] . "," . $fastaHash{$key};);
                use warnings qw(uninitialized);  #DEBUG:


                $fullLine = $allLines[$index] . "," . $fastaHash{$key}; #This line here gives the problems
                push(@completeLineArray, $fullLine);

                $index++;
            }

            else{

                $index++;
            }
        }
    }

close($fh);


}

$index is for looping through the array and @allLines contains all the lines from a read file. (<$fh> is my filehandle).

Edit 22-10-2012: I added the entire code to show where the variables are made

Upvotes: 1

Views: 222

Answers (1)

David W.
David W.

Reputation: 107090

Usually, Perl is pretty good at picking the exact line number in undefined issues.

Apparently, somewhere, something you think has a value doesn't. The easiest way to solve this is to simply print out the values before you do anything else. Try this:

use feature qq(say);

[...]

no warnings qw(uninitialized);  #DEBUG:
say qq(DEBUG: \$fastaHash{$key} = "$fastaHash{$key}");
say qq(DEBUG: \$fullLine = $allLines[$index] . "," . $fastaHash{$key};);
use warnings qw(uninitialized);  #DEBUG:
$fullLine = $allLines[$index] . "," . $fastaHash{$key};
push(@completeLineArray, $fullLine);

This will print out the values you're trying to concatenate together in $fullline which is where I believe the error is coming from. The push will work even if @completeLineArray is empty, and if $fullLine is the problem, it would be a problem in the line above anyway.

This is fairly simple to do. Simply copy out the line above and surround it with say qq(DEBUG:) and );. For extra bonus points, you can put a backslash in front of the $ just to make sure you don't have any problems with that.

The say command is available since 5.10, and is nice because I don't have to keep putting the \n at the end of these things which happens a lot because I cut and paste. You have to use the feature pragma in order to get it.

My suspicion is that $key is not a valid key in your %fastahash hash. Saying $fastahash{$key} when $key doesn't exist in your hash will return an undefined value. Since you didn't post much else, I can't say why $key would point to a non-existant value. However, I bet once you start printing out these keys, you'll quickly find the issue.

The no warnings qw(uninitialized) will stop printing out that uninitialized warning. I know that some value will be uninitailized in the DEBUG: statements. That's why I am printing them. However, reenable the uninitialized warnings before your statement, so that you still get that warning. You see that in your output, and you can look for the DEBUG: statements above to see what the issue could be.

After you figure out the problem, you can easily remove the DEBUG: lines with a search and delete.

Now, there are two ways of handling this error once you find it:

Ignore it

Just surround the code with the no warnings qw(uninitialized); and use warnings qw(initialized); statements. It's quick and simple and the program just might be doing what you want anyway. Besides, we all know if you ignore a problem, it just goes away.

Handle the Error

If, what I suspect is that $key is not pointing to a valid key in your array, then you can catch that error and handle it. It might simply be not pushing that value into your @completeLineArray array, or it might be some other error handling technique. Below, I check for two possibilities: That $key doesn't point to a valid entry in %fastaHash, or that $key does actually point to a valid entry in your %fastaHash, but that value is undefined:

if ( defined $fastaHash{$key} ) {
    $fullLine = $allLines[$index] . "," . $fastaHash{$key};
    push(@completeLineArray, $fullLine);
}
elsif ( not exists $fashaHash{$key} ){  #Key could exist, but value be `undef`
   ...;   #What you want to do if value key points to is undefined.
}
else (
   ...;   #What you want to do if $key doesn't point to a key in your hash
}

Upvotes: 1

Related Questions