Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the a list to show zeros for empty entries in Perl?

Tags:

perl

Originally, I am working with a list with length = 2^16. However, to abstract this, I will set length = 5 in this example.

#subroutine to make undefined entries -> 0
sub zeros {
    foreach(@_) {
        if(!defined($_))    {
            $_ = 0;
        }
    }
}       
 #print out and indicies and elements of list 
    sub checking {
        print "List = \n";
        my $counter = 0;
        foreach (@_) { 
            print "index = $counter\n";
            print "$_\n";
            $counter += 1;
        }
            print "\n";
    }

Method 1: If I access different indices to edit the element, I get the following when I print out the arrays. I dont want to see blank. I want them to be 0. I have already set up a subroutine "zeros" to make undefined entries become zero. But I dont know what went wrong in my code. I have also tried "$_ += 0" for each elements of the list. I still wasnt able to get zeros for empty entries.

#method 1
@abc = ();
$abc[1] = 3;
$abc[5] = 5;
&zeros(@abc);
&checking(@abc);
List = 
index = 0

index = 1
3
index = 2

index = 3

index = 4

index = 5
5

And method 2: I can get zeros if I initialise the list like this. But as I said, I am working with very long list, I cannot definitely not initialise my list like this.

#method 2
@abc = (3,0,0,0,5);
&checking(@abc);

List = 
index = 0
3
index = 1
0
index = 2
0
index = 3
0
index = 4
5
like image 637
mynameisJEFF Avatar asked Aug 06 '13 20:08

mynameisJEFF


2 Answers

Your approach is correct, but there's an issue with your zeros() function. You are calling it with @abc as a parameter, which makes a copy of that list. You then change the copy. At the end of the sub, that copy is discarded. In your checking() function, you are still using the original list.

You can fix it like this:

sub zeros {
  my @list = @_;
  @list = map { $_ // 0 } @list;
  return @list;
} 

@abc = zeros(@abc);
checking(@abc);

The trick is to return the altered list and reassign it to the original variable.

If you had used strict and warnings it would have told you about that:

Use of uninitialized value $_ in concatenation (.) or string at F:\scratch.pl line 28. List =  index = 0

index = 1 3 index = 2

index = 3

index = 4

index = 5 5

Use of uninitialized value $_ in concatenation (.) or string at F:\scratch.pl line 28. 
Use of uninitialized value $_ in concatenation (.) or string at F:\scratch.pl line 28. 
Use of uninitialized value $_ in concatenation (.) or string at F:\scratch.pl line 28.

But since you are dealing with a very big array, I would advise to use an array reference instead because the copying will be expensive.

sub zeros {
  $_ //= 0 for @{ $_[0] };
} 

zeros(\@abc);
checking(@abc);
like image 84
simbabque Avatar answered Sep 23 '22 15:09

simbabque


Can you initialise your list using

@abc = (0) x 2**16 

which sets it to a list of 2**16 zeroes?

I tried using your zeroes method. It worked if I initialise the array like this:

@abc = (undef, 1, undef, undef, undef, 5)

So it looks like the subroutine doesn't replace array-entries that don't exist (as opposed to existing but having a value of undef)

In which case you could try extending your zeros subroutine to return the modified array and assign that back to the original array:

#subroutine to make undefined entries -> 0
sub zeros {
    foreach(@_) {
        if(!defined($_))    {
            $_ = 0;
        }
    }
    return @_;
}       

@abc = ();
$abc[1] = 3;
$abc[5] = 5;
@abc = zeros(@abc);
# Check:
print "index = $_\n$abc[$_]\n" for 0..$#abc;

Alternatively, you could pass a reference to the original array:

#subroutine to make undefined entries -> 0
sub zeroref {
    my ($array) = @_; # Expect a single argument: An array-reference
    foreach(@$array) {
        if(!defined($_))    {
            $_ = 0;
        }
    }
}       

@abc = ();
$abc[1] = 3;
$abc[5] = 5;
zeroref(\@abc); # Pass an array-reference instead
# Check:
print "index = $_\n$abc[$_]\n" for 0..$#abc;
like image 26
Adrian Pronk Avatar answered Sep 20 '22 15:09

Adrian Pronk