Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Index number repeating in for loop

by DW10 (Initiate)
on Jun 28, 2013 at 21:21 UTC ( #1041347=perlquestion: print w/ replies, xml ) Need Help??
DW10 has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to automatically find the index of a certain array value by searching through an array with a for loop. This results in either the for loop repeating each index, or when I use 'last' or 'exit' the index counter doesn't work. Any help would be appreciated. Here's a simple code for what I've been attempting: Ideally, I want my output to be: F is at index 5

#!/usr/bin/perl #use strict; #use warnings; my @text = qw/A B C D E F G H I J/; for my $element (@text){ if ($element = "F") { print "$element is at index: $index_number\n"; $index_number++; } #last if ($element = "F") }

Either prints the text 10 times, each with different index or if I use last, prints once (good) but doesn't give an index (bad).

Comment on Index number repeating in for loop
Download Code
Re: Index number repeating in for loop
by hdb (Prior) on Jun 28, 2013 at 21:27 UTC

    You are confusing assignment and comparison.



      > You are confusing assignment and comparison.

      to be precise compare eq vs == vs =

      see perlop#Equality Operators and perlop#Assignment Operators

      Cheers Rolf

      ( addicted to the Perl Programming Language)

Re: Index number repeating in for loop
by AnomalousMonk (Abbot) on Jun 28, 2013 at 21:30 UTC

    A quick solution:

    >perl -wMstrict -le "my @text = qw/A B C D E F G H I J/; ;; I: for my $i (0 .. $#text) { next I unless $text[$i] eq 'F'; print qq{$text[$i] is at index $i}; last I; } " F is at index 5

    Updates: Some comments on your OPed code:

    •  $element = "F"   This expression assigns a string to a variable. Because the assigned string is always true, the true block of the if-statement is always executed. You may have intended to test for equality, and in that case you would need to use  eq to test for string equality (and not  == for numeric equality): e.g.  $element eq 'F'. (Already pointed out by hdb.)
    •  $index_number++;   This statement is within the true block of the if-statement which, had you been testing for equality to 'F', would only have been executed once for the entire set of example data. You would really need to count each and every index up to the target element value in order to get a valid index.
    •  $index_number   You have explicitly commented out warnings and strictures in your OPed code. The  $index_number variable should, IMHO, have been defined as a lexical (and perhaps even explicitly initialized to 0) outside the for-loop so it could be used inside the loop for index counting:
          my $index_number = 0;
      Without strictures and an explicit lexical definition, this variable is, horror of horrors, a global variable (shudder). (See johngg's second example here.)

    And here's another code example using a new capability of each available for arrays since Perl version 5.12:

    >perl -wMstrict -le "my @text = ('A' .. 'J'); ;; I: while (my ($i, $element) = each @text) { next I unless $element eq 'F'; print qq{$element is at index $i}; last I; } " F is at index 5

    More: And here's another variation on grep as suggested by davido. Note that it does not stop when it finds the first target match, but searches all elements of the array.

    >perl -wMstrict -le "my @text = qw/A B C D E F G H F I J/; ;; my @F_in_it = grep { $text[$_] eq 'F' } 0 .. $#text; ;; print qq{these indices have an 'F': @F_in_it}; " these indices have an 'F': 5 8

      Thank you all. That's incredibly helpful! I'll be sure to read up on Equality vs Assignment. Cheers

Re: Index number repeating in for loop
by johngg (Abbot) on Jun 28, 2013 at 21:38 UTC

    Two quick solutions, one the same as AnomalousMonk's but I'd already run it so I might as well post it!

    $ perl -Mstrict -Mwarnings -E ' my $want = q{F}; my @text = q{A} .. q{J}; for my $index ( 0 .. $#text ) { next unless $text[ $index ] eq $want; say qq{$want at $index}; last; } my $index; for my $elem ( @text ) { do { $index ++; next; } unless $elem eq $want; say qq{$want at $index}; last; }' F at 5 F at 5 $

    Cheers,

    JohnGG

Re: Index number repeating in for loop
by davido (Archbishop) on Jun 28, 2013 at 22:13 UTC

    ...or simply...

    print "'F' is at index: $_\n" for grep { $text[$_] eq 'F' } 0 .. $#text;

    List::MoreUtils provides a sugary alternative, "indexes":

    use List::MoreUtils qw( indexes ); # ... print "'F' is at index: $_\n" for indexes { $_ eq 'F' } @text;

    This is a case where I prefer grep because what it's doing isn't unclear or awkward enough to justify the module (imho).


    Dave

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1041347]
Approved by hdb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (14)
As of 2014-12-18 12:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (51 votes), past polls