Hi PERL-fans,

I have a problem with an array while coding a histogram:

The data is in an array

@data

I initialise my histogram array like:

@histo=();

Then, I loop over the datapoints and at each point compute in which bin that point would be:

for(my $i=0; $i<scalar(@data); $i++){
  my $j=int(($data[$i]-$min)/$bin_width + 1);
  $histo[$j]++;
}

The problem is, that there might be bins which are empty (if the histogram is not coarse). And the empty bins should be assigned to ZERO and not stay undef, as they are now.
I tried looping over the whole array histo after the procedure and checking each value if it was a number or not and set all non-numbers to zero, but this seems to be not really a nice and good solution... I also tried to initialise the histo array at the beginning (as i actually now how many bins i will have) with a for loop for 0..fullsize setting all the values to zero, however, i think there must be a better way of initialising an array properly.

many thanks for your advice!

Recommended Answers

All 7 Replies

Why not just put in a line like this:

$data[$i]=0 if (!$data[$i]);

I assumed that the $data[$i] is the one you're having problems with. If not, you can used that with the other array.

Initialising the array in advance with a loop doesn't seem like a bad approach, either. It takes only about one line.

#!/usr/bin/perl
use strict;
use warnings;

my @data = (); #Empty array with no elements
my $how_many_bins = 25; #Arbitrary example

#The following loop pushes a zero into the array for each element of a range.
#Remember array indexing starts at 0 so greatest index = $how_many_bins - 1
push @data, 0 foreach (0..$how_many_bins - 1);

print join ', ', @data;

thanks, mitchems,
the histo array is the problem, the data is all well-defined. in the code i posted, i do not loop over the histo array, just over the data array, that is why i cannot use something like you suggested. currently, i use this to pre-define the histo array:

for(my $j=0; $j<$N; $j++){
   $histo[$j]=0;
}

like this, i set all the N values of the histo array to zero. Is there another way of setting all the values of an array to zero, (if i know how many elements the array has) other than looping over the whole array?

d5e5, thanks, in the meantime also for your reply!
so, is my for loop or your push-foreach solution quicker?

If you don't know how many are in the array until after you assign the values you can do this:

my $max=0;
for(my $i=0; $i<scalar(@data); $i++){
  my $j=int(($data[$i]-$min)/$bin_width + 1);
  $max=$j if($j>$max);
  $histo[$j]++;
}
my $x=0;
for ($x=0;$x<$max;$x++){
	$histo[$x]=0 if(!$histo[$x]);
}

I didn't get a chance to actually run that code BTW.

d5e5, thanks, in the meantime also for your reply!
so, is my for loop or your push-foreach solution quicker?

I don't know which runs quicker. My push foreach is quicker for me to understand, but maybe that's just a personal preference.

I haven't benchmarked it but I suspect a map statement would be the fastest to run, because perl already has the loop logic pre-defined in the map function.

map $data[$_] = 0, (0..$how_many_bins - 1); #This may run faster than foreach loop.

thanks for both of you!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.