Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

reiterateing over array

by k0rn (Acolyte)
on Aug 19, 2008 at 19:52 UTC ( [id://705319]=perlquestion: print w/replies, xml ) Need Help??

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

I need to take a variable and then reiterate over and array until the variable match's one of the values in the array.

Then stop and print something.

This block of code is what Im trying to get working.

if ($event eq 'JOIN') {

open (PROTECTED, "$protected");

@protected = <PROTECTED>;

close(PROTECTED);

for $_ (@protected) {

if ($_ eq $user[0]) {

&sock("PRIVMSG $tag

:$user[0] Is A Protected User! $_");

}

}

}

Replies are listed 'Best First'.
Re: reiterateing over array
by TGI (Parson) on Aug 19, 2008 at 22:43 UTC

    So, you need to find matches for a variable in an array? Is the variable a scalar, an array or a hash?

    It sounds like you are looking for the first item only.

    In the examples below, the built-in grep and first from List::Util are fairly interchangeable. Use grep if you want all the matching items. Use first if you only want the first match. Look at the first two examples, and notice the differences between them to see how to alter subsequent examples to use first.

    use strict; use warnings; use List::Util qw(first); my @array_to_search = (1..5) x 2; my $target_value = 3; my @target_values = (5, 4); { # Find the first target and do something to it. my $match = first { $target_value == $_ } @array_to_search; matches_found( $match ); } { # Find all matches and do stuff. my @matches = grep { $target_value == $_ } @array_to_search; matches_found( @matches ); } { # match list with nested loop matching my @matches; foreach my $target ( @target_values ) { push @matches, grep { $target_value == $_ } @array_to_search; } matches_found( @matches ); } { # match list with a hash lookup my %target; @target{ @target_values } = (); my @matches = grep { exists $target{$_} } @array_to_search; matches_found( @matches ); }

    BTW, I noticed a couple of other things in your code that could lead to problems. I've added comments below.

    if ($event eq 'JOIN') { # indent your code. It doesn't matter if you + use tabs, 2 spaces, or 4 spaces per level, with GNU or K&R or any ot +her bracketing. Just pick a style and use it. open (PROTECTED, "$protected"); # two element open. Global file handle in use. No error checking. U +nnecessary stringification. @protected = <PROTECTED>; # You are leaving line endings on your list + items. Is this what you meant to do? This probably why what you ha +ve now isn't working. close(PROTECTED); # no error checking. for $_ (@protected) { #WTF? No need to add $_ to for declaration. if ($_ eq $user[0]) { # Do you really need to override prototypes on your function called s +ock? &subroutine() has a specific meaning. See perlsub for more info +. sock() is not very descriptive as function names go. Try somethin +g like send_message() or send_message_to_client(). &sock("PRIVMSG $tag :$user[0] Is A Protected User! $_"); # If you want to have multiline variables, use a heredoc. Otherwise c +onstruct them. Dangling lines like this is asking for trouble. } } }

    Same code cleaned up:

    if ($event eq 'JOIN') { # Read in protected user ids open (my $protected_fh, '<', $protected) or die "Unable to open $protected: $!\n"; my @protected = <$protected>; chomp @protected; close(PROTECTED) or die "Unable to close $protected: $!\n" # Verify that $user[0] is not protected. foreach my $protected_uid (@protected) { if( $protected_uid eq $user[0] ) { sock( join "\n", "PRIVMSG $tag", '', ":$user[0] Is A Protected User! $protected_uid", ); last; # stop processing after first match found. } } }

    If you aren't already doing so, use strict and warnings. If you are new to Perl and don't recognize the various error messages that these pragmata generate, use diagnostics as well.

    Map, grep, first and similar functions are powerful tools that help perl programmers create simple, powerful programs. But good old-fashioned for-loops can do the same jobs--maybe with more typing, maybe a bit less efficiently, but they still get it done. If you don't understand map and friends, study them until you do, but keep using foreach and while in the meantime.

    Updated: Fixed error in my code thanks to JadeNB. My error emphasizes my points about using strictures. If I had run this under strict, the error would have been caught by the compiler.


    TGI says moo

      As a very minor matter, note that you iterate over $protected_uid but check $protected_id. This could be why your change didn't work for k0rn.
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: reiterateing over array
by kyle (Abbot) on Aug 19, 2008 at 20:26 UTC

    You may be interested in List::Util::first:

    use List::Util qw( first ); my $pro = first { $user[0] eq $_ } @protected; do_stuff_with( $pro ) if defined $pro;

    Considering the rest of your code, however, you might want to look into a hash for storing your protected users persistently rather than reading a file every time someone joins. See perldata for info on hashes.

      I could use a hash but if the bot ever goes down then the list of protected users is gone. Thats why Im opening the list from a .txt file and putting the contents in the an array. So the only way the protected users list would be lost is if i deleted the .txt file. Unless you meant in some other way.

        You might want to use something like DBM::Deep that lets you tie a hash into a file. Thus, you get the simplicity of using a hash for quick access and the persistence of the data in a file.

        I could use a hash but if the bot ever goes down then the list of protected users is gone. Thats why Im opening the list from a .txt file and putting the contents in the an array.

        I personally believe that if you can open the list from a .txt file an put its contents into an array, then you could also put them into an a hash. unless you meant in some other way! ;)

        --
        If you can't understand the incipit, then please check the IPB Campaign.
        And I did not understand this

        use List::Util qw( first ); my $pro = first { $user[0] eq $_ } @protected; do_stuff_with( $pro ) if defined $pro;
Re: reiterateing over array
by dwm042 (Priest) on Aug 19, 2008 at 21:47 UTC
    Are you trying to do something like this?

    #!/usr/bin/perl use warnings; use strict; my $variable = "foo"; my @array=<DATA>; for (@array) { print if ( /$variable/ ); } __DATA__ able baker cad dexter edwin foo george harry irvin jake
    The output is:

    C:\>perl check_in_array.pl foo
Re: reiterateing over array
by injunjoel (Priest) on Aug 19, 2008 at 20:55 UTC
    Greetings,
    Another way to look at this problem is to use grep to simply see if $user[0] is in your @protected list.
    open (PROTECTED, "$protected"); @protected = <PROTECTED>; close(PROTECTED); #... not sure where $tag is coming from... if (grep($_ eq $user[0], @protected)){ sock("PRIVMSG $tag:$user[0] Is A Protected User!"); }
    However if you are looking for a counter of where in the list $user[0] appears you can add one to your for loop.
    my $count = 0; for(@protected){ if($_ eq $user[0]){ sock(...blah blah blah...); last; } $count++; } print("$user[0] was found at ".$count+1." in the list.\n");


    -InjunJoel
    "I do not feel obliged to believe that the same God who endowed us with sense, reason and intellect has intended us to forego their use." -Galileo
Re: reiterateing over array
by Perlbotics (Archbishop) on Aug 19, 2008 at 20:34 UTC
    You might be interested in last too?
Re: reiterateing over array
by FunkyMonk (Chancellor) on Aug 19, 2008 at 19:56 UTC
    Are you looking for next?

    But, I'm not convinced I understood the question ;)

    Yep. I was right. I didn't understand the question. Sorry.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (6)
As of 2024-03-29 01:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found