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

Hi Monks!
In my code a have this foreach loop that calls a sub routine to check names in the database, that's ok, but my problem is that I need to capture how many names was actually passed to this sub since the call happens one at a time. Lets say that this arrays @names has 100 elements, but only a certain number of elements qualify to be passed to the check_names sub. I hope I am making myself clear.
Here is a sample code to illustrate what I am trying to say:
... foreach my $name (@names) { # Skip if it doesn't contain data. next unless $name; check_names($name); } ... sub check_names { my(@names) = @_; my $how_many_names_total = @names; print "$how_many_names_total"; } ...

Thanks for looking!

Replies are listed 'Best First'.
Re: Counting in loop help!
by Kenosis (Priest) on Jul 26, 2012 at 20:29 UTC

    Perhaps using a state variable within the sub will work for you:

    use Modern::Perl; for ( 1 .. 10 ) { my @names = (qw/Fred Barney Wilma Betty Bam-Bam Perl Java C++ Ruby Lisp/) [ 0 .. int( rand(10) ) ]; my ( $how_many, $count ) = check_names(@names); say "How Many Names: $how_many\nCount: $count\n"; } sub check_names { my (@names) = @_; state $count = 0; $count++; my $how_many_names_total = @names; return $how_many_names_total, $count; }

    Output:

    How Many Names: 1 Count: 1 How Many Names: 3 Count: 2 How Many Names: 5 Count: 3 How Many Names: 9 Count: 4 How Many Names: 1 Count: 5 How Many Names: 5 Count: 6 How Many Names: 5 Count: 7 How Many Names: 9 Count: 8 How Many Names: 2 Count: 9 How Many Names: 7 Count: 10

    Hope this helps!

      That would help, but I only have to print the last value: "How Many Names: 7 Count: 10".
Re: Counting in loop help!
by aitap (Curate) on Jul 26, 2012 at 19:50 UTC
    my $i=0; # this variable will be visible in the foreach scope foreach my $name (@names) { next unless $name; ++$i; # autoincrement check_names($name); } say $i;
    Sorry if my advice was wrong.
Re: Counting in loop help!
by Rudolf (Pilgrim) on Jul 26, 2012 at 19:53 UTC

    Im not sure I fully understand your question, but I will try to answer it. I'm not sure why your using a list down in check_names to get your argument. but anyway I would just use counter, if you want to incorporate it into the for loop perhaps or you can put it outside..

    my $how_many_names_total = 0; foreach my $name(@names){ if($name){ $how_many_names_total++; check_names($name); } else{ next; } }
      The count has to be done from the check_names sub, the way you did its OK but the trick part is to capture the last time the check_names sub was called inside of it.

        is it possible you can remove the invalid names before going through the list? for example create a new array with the valid names.. find the number of them and then test the id against the array element in your subroutine:

        my @raw_names = ...; my @valid_names = (); my $total_valid_names = -1; foreach my $raw_name(@raw_names){ next unless $raw_name; push(@valid_names,$raw_name); $total_names++; } for(my $i=0;$i<length(@valid_names);$i++){ check_name($valid_names[$i],$i); } sub check_names{ my($name,$id) = @_; if($id == $total_valid_names){ say "$name is the last name! ($idth)"; } }