Completed: a much simpler Servers and Operating Systems section of the Community. We combined many of the older boards, so you won't have to click through so many levels to get at the information you need. Check the consolidated boards here as many sub-forums are now single boards.
If you have bookmarked forums or discussion boards in Servers and Operating Systems, we suggest you check and update them as needed.
Languages and Scripting
cancel
Showing results for
Did you mean:

SOLVED
Go to solution

## How to find the minimum value in an array in PERL

Hi,

My values in an array are in the form hours:mins:secs.
I want to find the minimum of these values.

10 REPLIES
Acclaimed Contributor
Solution

## Re: How to find the minimum value in an array in PERL

Hi:

This builds on what I showed you yesterday.

# cat ./findmin
#!/usr/bin/perl
use strict;
use warnings;
my @times = ( "91:02:03", "02:11:17", "00:08:11", "03:33:33" );
my \$idx = -1;
my \$minidx = 0;
my \$mintime = 0;
for my \$t (@times) {
\$idx++;
my (\$hr, \$min, \$sec) = split /:/, \$t;
my \$elapsed = (\$hr * 3600) + (\$min * 60) + \$sec;
\$mintime = \$elapsed if \$mintime == 0;
if (\$elapsed < \$mintime) {
\$mintime = \$elapsed;
\$minidx = \$idx;
}
}
print "mininum is \$times[\$minidx] at element \$minidx\n";
1;

...I have used a list (array) called "@times" with four 0-relative elements in the format "hh:mm:ss".

We iterate over the list, converting each element into a number of seconds. We track the index number of the array along with the smallest value (in seconds).

At the end, we simply print the "hh:mm:ss" and the element number that represents the minimum.

# ./findmin
mininum is 00:08:11 at element 2

Regards!

...JRF...
Honored Contributor

## Re: How to find the minimum value in an array in PERL

Try to sort the array and take the first element

HTH
Entities are not to be multiplied beyond necessity - RTFM
Honored Contributor

## Re: How to find the minimum value in an array in PERL

The solution JRF is more resource effective than sorting, and also delivers the position of the min value in the original array.
If the is usefull for you, or if you also need to pick up the max then walk teh list as indicated.

If it is a modest size list (thousands, not millions) then as Victor indicates, just sort the array.

Example:
use strict;
use warnings;
my @times = ( "91:02:03", "02:11:17", "00:08:11", "03:33:33" );
my @sorted_times = sort @times;
print join(' - ', @sorted_times), "\n";
print "min = \$sorted_times[0]\n";
print "max = \$sorted_times[@sorted_times - 1]\n";

Cheers,
Hein.

## Re: How to find the minimum value in an array in PERL

The array has value in the form of hrs:mins:secs

Will the direct sort work or we have to convert the values in seconds and then sort using the sort function.
Acclaimed Contributor

## Re: How to find the minimum value in an array in PERL

Hi (again):

The answer to your last question of whether or not a direct sort will work, or whether you will have to first convert to seconds, depends upon your data. Consider:

# perl -le '@a=qw(1:17:19 01:17:17 1:33:48 01:34:48);print for sort (@)'

01:17:17
01:34:48
1:17:19
1:33:48

...is *not* ordered the way you want; but:

# perl -le '@a=qw(1:17:19 1:17:17 1:33:48 1:34:48);print for sort (@a)'

...is ordered correctly.

Thus, it is simpler to convert to epoch seconds; walk through the array; and track the mininimum value and index of the original data. Of course, a more complicated sort can be written if that was the goal in the first place.

Regards!

...JRF...
Honored Contributor

## Re: How to find the minimum value in an array in PERL

Right, I used a implies string sort which relies on a consisten format. If the format is not exactly predictable, then you need to convert to formatted string, or to numeric first.
You can tell sort to use a function to do all that:

use strict;
use warnings;

sub seconds{
my (\$hr, \$min, \$sec) = split /:/, \$_[0];
return (\$hr * 3600) + (\$min * 60) + \$sec;
}

my @times = qw(1:17:19 01:17:17 1:33:48 01:34:48);
my @sorted_times = sort @times;
print join(' - ', @sorted_times), "\n";
print "min - \$sorted_times[0]\n";
print "max - \$sorted_times[@sorted_times - 1]\n\n";

@sorted_times = sort {&seconds(\$a) <=> &seconds(\$b)} @times;
print join(' - ', @sorted_times), "\n";
print "min = \$sorted_times[0]\n";
print "max = \$sorted_times[@sorted_times - 1]\n";

fwiw,
Hein.

## Re: How to find the minimum value in an array in PERL

Thanks for all help on sorting.

while(my \$data = \$sth->fetchrow_hashref) {
my %loopdata;
(\$Hrs,\$Mins,\$Secs) = &diffDateTime(\$data->{'date'},\$data->{'time_in'},\$data->{'time_out'},\$data->{'date_out'});
\$loopdata{'type'}=\$data->{'type'};
\$loopdata{'interval'}= "\$Hrs:\$Mins:\$Secs";
push(@intlist, \%loopdata);

}

Please tell me whether the code is correct.
Honored Contributor

## Re: How to find the minimum value in an array in PERL

Only you can tell.
First does it compile by now without raising sysntax errors and warnings?
Run perl -cw on your script.
But this won't tell if the code executes correctly.
We don't know the database's table you are querying, and therefore cannot tell whether the field names you used as keys to your result set are ok.
I would suggest you run your code in the Perl debugger and have a look at what \$data contains after each fetch.
Alternatively you could use Data::Dumper or YAML, but using the debugger is easier.
perl -d /your/script.pl
will lead you into a debug session.
Continue to the first statement in the while loop (c line#).
There have a look at \$data in all its beauty
|x \$data
This will clarify the structure of your hash.
You can step through your code by just hitting Return, and repeat the data dump.

## Re: How to find the minimum value in an array in PERL

My code is like this -->

my \$con_sql = "SELECT type,date,time_in,time_out,date_out ".
"FROM contract_log,contract_times WHERE ".
"contract_log.refid=contract_times.conid AND date BETWEEN '\$fromDate' AND '\$toDate' AND date_out<>'0000-00-00'";
my \$dbh = &TpsUtils::db_connect();
my \$sth = \$dbh->prepare(\$con_sql);
die "Error with SQL: \$con_sql" if !defined \$sth->execute;

my @intlist;
my (\$Hrs,\$Mins,\$Secs);
use Data::Dumper;
open(FILE,'>/home/pankaj/report/test.txt');

#store the time intervals in the array @intlist
while(my \$data = \$sth->fetchrow_hashref) {
my %loopdata;
(\$Hrs,\$Mins,\$Secs) = &diffDateTime(\$data->{'date'},\$data->{'time_in'},\$data->{'time_out'},\$data->{'date_out'});
\$loopdata{'type'}=\$data->{'type'};
\$loopdata{'interval'}= "\$Hrs:\$Mins:\$Secs";
push(@intlist, \%loopdata);

}

print FILE Dumper(\@intlist);

When I run the query directly I get data but when I dump that data(@intlist) in a file I can't find any data.

Please tell me whats going wrong.
Highlighted