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

Hi, I was wondering if there was a way to.. suspend a loop? I have a large while loop, and in the middle of it, i need to sort an array and print the highest variable, however, it prints it abotu 30 times, becasoe of the loop. So basically, i want to stop the loop, sort the array, and print the highest value, then continue the loop right after that exactly where it left off. Is that possible?
Thank You

Dipul Patel

Replies are listed 'Best First'.
Re: Breaking a Loop
by chromatic (Archbishop) on Oct 10, 2000 at 22:21 UTC
    You can call a subroutine in the middle of the loop. When it returns, loop execution will continue.
      Hi guys, thanks for the speedy reply. The problem i guess is that i only want the subroutine, or array sorted once, and it isnt defined until the END of the loop.. lemme attach the code, and hopefully it will help
      #!/usr/local/bin/perl # Author: Dipul Patel # This Perl Script takes a home site chosen by the user, then calcula +tes # the distance from that home site to every site in the system and pr +ints # in a HTML table. #--------------------------------------------------------------------- # Process information for main site #--------------------------------------------------------------------- $lat_long = "/tmp/sitesLL"; $filepath = "/data1/PHL/neighbors"; $query_string = $ENV{'QUERY_STRING'}; @search = split(/&/,$query_string); @info = split(/=/, $search[0]); @siteinfo = split(/-/, $info[1]); print "Content-type: text/html\n\n"; #read in lat and long file open(LL, $lat_long); @lat_long = <LL>; close(LL); #Get long,lat,g,h,j for main site @dataline = grep /^$siteinfo[0]/, @lat_long; @dataparse = split(/\|/, $dataline[0]); ($sitelat, $sitelong) = split(/,/, $dataparse[3]); $g = $dataparse[4]; $h = $dataparse[5]; $j = $dataparse[6]; #--------------------------------------------------------------------- # Process information for every other site, one at a time #--------------------------------------------------------------------- #open directory and get sites names opendir DIR, $filepath; @allfiles = grep !/^\.\.?$/, readdir DIR; closedir DIR; @allfiles = sort @allfiles; $totalsite=@allfiles; @allfiles2=@allfiles; foreach $site(@allfiles) { chomp $site; @frst = split(/[a-z][a-z]/, $site); @cell = split(/[A-Z]/, $frst[1]); push(@othersiteinfo, $cell[0]); } #Open assiociated neighbor list file open(IN, "$filepath/$siteinfo[1]"); @data=<IN>; close(IN); #get sector numbers for neighbors foreach $line(@data){ #chomp $line; @information = split (/\|/, $line); push (@neighbor,$information[1]); } $n=-1; $temphigh = 0; while($n<$totalsite){ $n++; @dataline2 = grep /^$othersiteinfo[$n]/, @lat_long; @dataparse2 = split(/\|/, $dataline2[0]); ($sitelat2, $sitelong2) = split(/,/, $dataparse2[3]); $g2 = $dataparse2[4]; $h2 = $dataparse2[5]; $j2 = $dataparse2[6]; #--------------------------------------------------------------------- # calculate distance from main site to other sites #--------------------------------------------------------------------- $a=($g2-$g)*($g2-$g); $b=($h2-$h)*($h2-$h); $c=($j2-$j)*($j2-$j); $abc=($a+$b+$c); $sqabc=sqrt($abc); $distance=(3960*$sqabc); $distance = sprintf "%1.2f", $distance; $distance2=$distance; $distance3=$distance; $distance4=$distance; if ($temphighval >= $temphigh){ $temphigh=$temphighval; } if ( $distance > 10){ next; } # if ( $distance == 0){ # next; # } # The following code, first compares the sector number of the current + site to that of the neighbor list, # then it complies 2 arrays, one with all the neighbors, the other ar +ray with the other sites. $element = $othersiteinfo[$n]; if (grep {$_ eq $element} @neighbor) { @array3=($allfiles[$n],$distance2); push (@test1, @array3); push (@highval, $distance2); } else{ @array2=($allfiles[$n],$distance); push (@test2, @array2); } }#end whileloop my $done_sort=0; # or some more meaningful name while( $cond) { # probably some code here unless( $done_sort) { sort_the_array( @array); $done_sort=1; } # more code here } #create hash and sorted array for non-neighbors %distance=@test2; @sorted = sort { $distance{$a} <=> $distance{$b} } keys %distance; #extract sector numbers from sitename for use in hyperlinks. $k=0; @nonneighsect=@sorted; for ($h=0; $h<=$#nonneighsect; $h++) { $nonneighsect[$h] =~ s/\w{2}(\d{4})\w+/$1/; } #create hash and sorted array for neighbors %distance2=@test1; @sorted2 = sort { $distance2{$a} <=> $distance2{$b} } keys %distan +ce2; #extract sector numbers from sitename for use in hyperlinks. $j=0; @neighsect=@sorted2; for ($i=0; $i<=$#neighsect; $i++) { $neighsect[$i] =~ s/\w{2}(\d{4})\w+/$1/; } #-------------------- # the following code prints a table, with all the sites sorted first b +y neighbor, then distance. It also provides links # to automattically calculate distances for other sites, as well as ma +p them. #-------------------- print "<HTML>\n"; print "<HEAD><TITLE>Distance Tool</TITLE></HEAD>\n"; print "<TABLE BORDER=1 cellspacing=1 cellpadding=1 WIDTH =65%>\n"; print "<TR><TH Colspan = 4> Distance From $siteinfo[1] To:<TH>"; # print " <FONT SIZE=\-5><A HREF=\"http://www-mat.nextel.com/cg +i-bin/rfn-cgi/neighbormap2.cgi?frames=frames&site=$siteinfo[0]-$sitei +nfo[1]&rpt=Daily-Total&Lfactor=150000&sector=1\" target=_top>1</a></f +ont>\n"; # print " <FONT SIZE=\-5><A HREF=\"http://www-mat.nextel.com/cg +i-bin/rfn-cgi/neighbormap2.cgi?frames=frames&site=$siteinfo[0]-$sitei +nfo[1]&rpt=Daily-Total&Lfactor=150000&sector=2\" target=_top>2</a></f +ont>\n"; # print " <FONT SIZE=\-5><A HREF=\"http://www-mat.nextel.com/cg +i-bin/rfn-cgi/neighbormap2.cgi?frames=frames&site=$siteinfo[0]-$sitei +nfo[1]&rpt=Daily-Total&Lfactor=150000&sector=3\" target=_top>3</a></f +ont>\n"; print "<FONT SIZE =\-5>"; print "<TR><TH>Site<TH>Distance<TH>Neighbor<TH>Map(sector)\n"; foreach $site3 (@sorted2) { print " <TR><TD><FONT SIZE=\-5><A HREF=\"http://www-mat.ne +xtel.com/cgi-bin/rfn-cgi/distance.cgi?site=$neighsect[$j]-$site3\" >$ +site3<TD>$distance2{$site3}<TD align=center>YES</font>\n"; print " <TD align=center><FONT SIZE=\-5><A HREF=\"http://w +ww-mat.nextel.com/cgi-bin/rfn-cgi/neighbormap2.cgi?frames=frames&site +=$neighsect[$j]-$site3&rpt=Daily-Total&Lfactor=150000&sector=1\" targ +et=_top>1</a></font>\n"; print " <FONT SIZE=\-5><A HREF=\"http://www-mat.nextel.com +/cgi-bin/rfn-cgi/neighbormap2.cgi?frames=frames&site=$neighsect[$j]-$ +site3&rpt=Daily-Total&Lfactor=150000&sector=2\" target=_top>2</a></fo +nt>\n"; print " <FONT SIZE=\-5><A HREF=\"http://www-mat.nextel.com +/cgi-bin/rfn-cgi/neighbormap2.cgi?frames=frames&site=$neighsect[$j]-$ +site3&rpt=Daily-Total&Lfactor=150000&sector=3\" target=_top>3</a></fo +nt>\n"; $j++; } foreach $site2 (@sorted) { print " <TR><TD><FONT SIZE=\-5><A HREF=\"http://www-mat.ne +xtel.com/cgi-bin/rfn-cgi/distance.cgi?site=$nonneighsect[$k]-$site2\" +>$site2<TD>$distance{$site2}<TD align=center>NO</font>\n"; print " <TD align=center><FONT SIZE=\-5><A HREF=\"http://w +ww-mat.nextel.com/cgi-bin/rfn-cgi/neighbormap2.cgi?frames=frames&site +=$nonneighsect[$k]-$site2&rpt=Daily-Total&Lfactor=150000&sector=1\" t +arget=_top>1</a></font>\n"; print " <FONT SIZE=\-5><A HREF=\"http://www-mat.nextel.com +/cgi-bin/rfn-cgi/neighbormap2.cgi?frames=frames&site=$nonneighsect[$k +]-$site2&rpt=Daily-Total&Lfactor=150000&sector=2\" target=_top>2</a>< +/font>\n"; print " <FONT SIZE=\-5><A HREF=\"http://www-mat.nextel.com +/cgi-bin/rfn-cgi/neighbormap2.cgi?frames=frames&site=$nonneighsect[$k +]-$site2&rpt=Daily-Total&Lfactor=150000&sector=3\" target=_top>3</a>< +/font>\n"; $k++; } print "</FONT>"; print "</TABLE>\n"; print "</HTML>\n";
      now, what i want, is where it says
      if ( $distance > 10){ next; }
      i want the 10 to be replaced with the highest value of the array defined at the end of the loop:
      if (grep {$_ eq $element} @neighbor) { @array3=($allfiles[$n],$distance2); push (@test1, @array3); push (@highval, $distance2); }
      But.. that array is added to everytime the loop runs, and i need the highest value from it when it is complete, so i can specify the largest distance to map. I hope this helps.
      Dipul Patel
        So you don't want to sort the array, you want to find the max value in it. So write a subroutine to find the max value in your array and call that (just like chromatic suggested!)
        use strict; # ALWAYS!!!!!! # MaxElementInArray( @array ) sub MaxElementInArray { my $max = shift; my $next; $max = $next > $max ? $next : $max while $next = shift; return $max; } # MaxElementInArrayRef( \@array ) sub MaxElementInArrayRef { my $array_ref = shift; my $index = $#$array_ref; my $max = $$array_ref[$index]; $max = $$array_ref[$index] > $max ? $$array_ref[$index] : $max while --$index >= $[; return $max; }
        Update: While examining your code in response to your statement below, I've noticed quite a few style issues: You don't use strict, you are not using CGI.pm, and you are not using subroutines to improve the readability (and maintainability) of your code. I strongly suggest you look into these things. As for your issue of trying to use a number before you have calculated it... this reveals a failure to plan before coding. Now I suspect you will need to re-write much of this code just to get things in a causal order.
        Oh yeah, i forgot to mention, this is my second week of learning perl hehe :). Adam, where exactly should i place the code you gave me? I dont understand where to put it, and where/which one to call. Thanks
        Dipul Patel
Re: Breaking a Loop
by mirod (Canon) on Oct 10, 2000 at 22:23 UTC

    More likely than not there is a problem with the way your code is written, the code you want to run just once should probably be outside of the loop.

    Anyway, as a duct-tape kinda fix you can always do:

    my $done_sort=0; # or some more meaningful name while( $cond) { # probably some code here unless( $done_sort) { sort_the_array( @array); $done_sort=1; } # more code here }

    But there is probably a better way, which I can't find unless I see the code.

Re: Breaking a Loop
by Anonymous Monk on Oct 11, 2000 at 17:49 UTC
    Thanks for all your help guys, i rewrote the script using more subroutines, and after some re-ordering.. it worked out fine. Thanks again
    Dipul Patel
Re: Breaking a Loop
by merlyn (Sage) on Oct 10, 2000 at 22:26 UTC