Search Through List

G

Gomer

How can I search through a list in PERL? For example, I want to
do something like the following:

@namelist = ('JONES', 'SMITH', 'JOHNSON');

print "Enter name of teammate whose password you need to reset, then
press the ENTER key: \n";
$teammate = <STDIN>;

if (grep ($teammate, @namelist))
{ print "I can\'t let you do that...";}
else
{ print "You are going to reset the password for $teammate";}
 
S

surfking

While wandering through cyberspace on 28 Jan 2005 15:12:31 -0800 Gomer
said :
How can I search through a list in PERL? For example, I want to
do something like the following:

@namelist = ('JONES', 'SMITH', 'JOHNSON');

print "Enter name of teammate whose password you need to reset, then
press the ENTER key: \n";
$teammate = <STDIN>;

if (grep ($teammate, @namelist))
{ print "I can\'t let you do that...";}
else
{ print "You are going to reset the password for $teammate";}

------------------------------------------------------------------------
So, what's the secret here?

Thanks,
Brian

Perl does indeed have a "grep" builtin function, but it is for regular
expression matching, not searching for exact values in an array.
(see perldoc for some more information on regular expressions)

eg.

@list = ( "bob" , "bobby" , "fred" );
@matches = grep /bob/,@list;
# @matches would then contain "bob" and "bobby"

@list = ( "bob" , "bobby" , "fred" );
@matches = grep /^bob$/,@list;
# @matches would then contain just "bob"


or you could use a loop

$string = "bob";
for ( $count = 0 ; $count <= $#list ; ++$count )
{
if ( $string eq $list[$count] )
{
last;
}
}

if ( $count <= $#list )
{
print "I found \"$string\" in position $count\n";
}
else
{
print "\"$string\" not found\n";
}
 
C

Chris Mattern

Gomer said:
How can I search through a list in PERL? For example, I want to
do something like the following:

@namelist = ('JONES', 'SMITH', 'JOHNSON');

print "Enter name of teammate whose password you need to reset, then
press the ENTER key: \n";
$teammate = <STDIN>;

if (grep ($teammate, @namelist))
{ print "I can\'t let you do that...";}
else
{ print "You are going to reset the password for $teammate";}
Use a hash. You also need to chomp the newline off your input, BTW.

#!/usr/bin/perl

use strict;
use warnings;

my %namelist = (
JONES => undef,
SMITH => undef,
JOHNSON => undef
);

print "Enter name of teammate whose password you need to reset, ";
print "then press the ENTER key: \n";
chomp (my $teammate = <STDIN>);

if (exists $namelist{$teammate}) {
print "You are going to reset the password for $teammate\n"; }
else {
print "I can't let you do that...\n"; }

--
Christopher Mattern

"Which one you figure tracked us?"
"The ugly one, sir."
"...Could you be more specific?"
 
M

Martin Kissner

Gomer wrote :
How can I search through a list in PERL? For example, I want to
do something like the following:

@namelist = ('JONES', 'SMITH', 'JOHNSON');

print "Enter name of teammate whose password you need to reset, then
press the ENTER key: \n";
$teammate = <STDIN>;

if (grep ($teammate, @namelist))
{ print "I can\'t let you do that...";}
else
{ print "You are going to reset the password for $teammate";}

------------------------------------------------------------------------

There has already been posted a solution by Chris.

I have use this question for my own practice and wrote the script below,
which gives me an error/warning before it gives the expected output.

--- output ---
"Use of uninitialized value in concatenation (.) or string at
../teammate.pl line 16, <STDIN> line 1.
You are going to reset the password for JONES"
--- end output ---

I'd appreciate if one of the regulars could explain this behaviour.
The script wotks correctly if I use a variable ($name) instead of $_,
but I would like to figure out how I can use $_

Thanks in advance
Martin

--- start ---
#!/usr/bin/perl

use warnings;
use strict;

my @namelist = ('JONES', 'SMITH', 'JOHNSON');

print "Enter name of teammate whose password you need to reset, then
press the ENTER key: ";

chomp (my $teammate = <STDIN>);

while (pop @namelist)
{
# if ($teammate eq $_ ) # Case does matter
if ($teammate =~ /\b$_\b/i ) # Case does not matter
{
print "You are going to reset the password for $teammate\n";
# do stuff
exit;
}
}
print "I can't let you do that...\n";
--- end ---
 
M

Martin Kissner

Martin Kissner wrote :
I'd appreciate if one of the regulars could explain this behaviour.
The script wotks correctly if I use a variable ($name) instead of $_,
but I would like to figure out how I can use $_

Okay; I finally found out that the script I posted doesn't work
correctly at all.
Sorry for not testing thoroughly enough.

Below is a snippet of the (working) script I had in the first place.
Can someone explain if it is possible to use $_ instead of $name here at
all and if so, how it is done?

while (my $name = pop @namelist)
{
if ($teammate eq $name)
[...]
}
 
M

Martin Kissner

Abigail wrote :
My guess is that you do a little more than just substituting $_ by $name.

You are right; I did

while (my $name = pop @namelist)
{
if ($teammate eq $name)
{
...
}
}

You need to assign to $_ (or another variable) to be able to use the
value you just popped. And note that I moved the popping out of the
while condition - otherwise you would quit processing the elements of
@namelist as soon as you encounter an element that is 0, the empty string,
the string "0", or undefined.

Thanks for all your explanations.
This has clarified things.

Best regards
Martin
 
G

Gunnar Hjalmarsson

surfking said:
Gomer said :

Perl does indeed have a "grep" builtin function, but it is for regular
expression matching, not searching for exact values in an array.

What makes you believe that the BLOCK or EXPR that grep() evaluates only
may contain regular expressions??

perldoc -f grep
@list = ( "bob" , "bobby" , "fred" );
@matches = grep /bob/,@list;

Or:

@matches = grep index($_, 'bob') == 0, @list;
# @matches would then contain "bob" and "bobby"

@list = ( "bob" , "bobby" , "fred" );
@matches = grep /^bob$/,@list;

Or:

@matches = grep $_ eq 'bob', @list;
 
M

Martin Kissner

Tad McClellan wrote :
if (lc $teammate eq lc $_ ) # Case does not matter

Thank you for that hint.
I guess it is "better" because no regex evaluation is necessary to
return the same result.

Regards
Martin
 
T

Tad McClellan

Martin Kissner said:
Tad McClellan wrote :


I forgot to mention it earlier, but your pattern was not correct,
it should be using ^ and $ anchors instead of \b anchors.

Thank you for that hint.
I guess it is "better" because no regex evaluation is necessary to
return the same result.


Right, kinda.

The primary reason it is better IMO is because it *looks like*
an equality test.

$teammate =~ /^$_$/i vs. lc $teammate eq lc $_

You have to think about the first one for a second to realize
that it is an equality test in disguise.

I eschew disguising production code. :)

A secondary reason is we don't have to concern ourselves with
regex metacharacters that might be in $_.

Saving CPU cycles would be a last reason, as should many
performance optimizations.
 
B

Bill Smith

Gomer said:
How can I search through a list in PERL? For example, I want to
do something like the following:

@namelist = ('JONES', 'SMITH', 'JOHNSON');

print "Enter name of teammate whose password you need to reset, then
press the ENTER key: \n";
########### $teammate = <STDIN>;
chomp($teammate = said:
##########if (grep ($teammate, @namelist))
unless (grep /^$teammate$/i, @namelist)
{ print "I can\'t let you do that...";}
else
{ print "You are going to reset the password for $teammate";}

----------------------------------------------------------------------
--

Use a matching expression in grep. Note that in scalar context, grep
returns the number of matches. In this case it will be either
1 (true), or 0 (false). I changed the sense of the match
because your messages suggest that you do want to change teammate
passwords, but no others.

Removing the return with chomp simplifies the match. It also removes
the
return from the second print statement. I recommend appending a "\n" to
both print messages.

Bill
 
M

Martin Kissner

Tad McClellan wrote :
I forgot to mention it earlier, but your pattern was not correct,
it should be using ^ and $ anchors instead of \b anchors.

Oh, that's right (of course).
Else I would get a match if I tried to reset the password of Mr. Jones
[...]
The primary reason it is better IMO is because it *looks like*
an equality test.

$teammate =~ /^$_$/i vs. lc $teammate eq lc $_

You have to think about the first one for a second to realize
that it is an equality test in disguise.

I eschew disguising production code. :)

Thank you for pointing that out.
If one would look at it really strictly it should be
$teammate eq $_
since Jones ne JONES

To me this is mainly a question of understanding Perl.
To the OP it might be a question of convenience, fault liability and
maybe even security.

Thanks again for your help.
Martin
 
T

Tad McClellan

Martin Kissner said:
Tad McClellan wrote :


If one would look at it really strictly it should be
$teammate eq $_
since Jones ne JONES


No, that would be for looking at the # Case matters
statement really strictly.

We were discussing the # Case does not matter
errr, case. :)

Looking at it strictly is also looking at it literally then.

(I *like it* when it looks like what it means.)

To me this is mainly a question of understanding Perl.


I don't see it that way.

It is mainly a question of communicating in the most clear
way possible. It is Software Engineering rather than Perl.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,166
Messages
2,570,907
Members
47,446
Latest member
Pycoder

Latest Threads

Top