Should I write my own Grep or Index function ?

M

Mark

Hi all,

I tried to find the way to search the first occurence of a string into
a list (which is a sub-set of a file) in order to know if this string
occurs at least one time anywhere.

I've read the perldoc -f grep and perldoc -f index but it seems that
these two functions does not allow me to do it in a simple way.

So do I have to write my own index function ?

I tried something like the following, but it seems that I do not handle
properly the line I passed to the function:

#!/usr/bin/perl -w
#!C:\Perl\bin\perl.exe -w

use strict;
use warnings;
use Benchmark;

my @f_lines = (<DATA>);
my $i = "aaaaaef";
my ($count, $start, $end);

print "\n$0: String searched is $i\n\n";

&start_bm;
$count = grep (/$i/i, @f_lines) ;
&print_bm("GREP: returned $count, ");

&start_bm;
$count = &my_index ("$i",@f_lines) ;
&print_bm("MY_INDEX: returned $count, ");

sub my_index() {
# $_[0]: searched string
# $_[1]: list

my $tag = $_[0];
my @list = $_[1];
my $n;

foreach (<@list>) {
$n = index($_, /$tag/i);
if ($n) {
return 1;
}
}
return 0;
}

##
## Functions
##

sub start_bm { $start = new Benchmark; }

sub print_bm() {
$end = new Benchmark;
printf $_[0]."%s\n", timestr(timediff($end, $start),'auto');
}

###########################################################################


TIA for any help,

MA
 
D

Dave Weaver

Hi all,

I tried to find the way to search the first occurence of a string into
a list (which is a sub-set of a file) in order to know if this string
occurs at least one time anywhere.

I've read the perldoc -f grep and perldoc -f index but it seems that
these two functions does not allow me to do it in a simple way.

grep() isn't simple? How so?
#!/usr/bin/perl -w
^^
Since you 'use warnings' (well done), the -w is unnecessary.
#!C:\Perl\bin\perl.exe -w

use strict;
use warnings;

A good start!
use Benchmark;

my @f_lines = (<DATA>);

There is no __DATA__ section in your script...
my $i = "aaaaaef";

$i is a poor choice of name for this variable. Yes, I'm being picky,
but proper variable naming is key to writing programs that other
people can understand. And "other people" includes yourself in 6
months time!
my ($count, $start, $end);

print "\n$0: String searched is $i\n\n";

&start_bm;
^
You should not use & on subroutine calls unless you require
the functionality it provides (you do not, in this case).
See perldoc perlsub for details.

Better written as:
start_bm();
$count = grep (/$i/i, @f_lines) ;

What's not simple about that?

Note that this may not do what you intend if $i has regular
expression metacharacters in it. In which case you might want:

$count = grep /\Q$i/i, @f_lines;
&print_bm("GREP: returned $count, ");

&start_bm;
$count = &my_index ("$i",@f_lines) ;
&print_bm("MY_INDEX: returned $count, ");

sub my_index() {
^^
Here you are specifying a prototype, indicating that my_index() takes
no arguments. You don't want or need the parentheses here.
(see: perldoc perlsub for information on prototypes).

sub my_index {
# $_[0]: searched string
# $_[1]: list

my $tag = $_[0];
my @list = $_[1];

That doesn't do what you think it's doing. $_[1] contains one single
scalar, in the case of your call above it's the value of $f_lines[0].
It doesn't (and can't) contain the whole array.

my ( $tag, @list ) = @_;
my $n;

foreach (<@list>) {
^ ^

Why the <...> ? This is a glob operator (see: perldoc -f glob) and
returns a list of filenames. Not what you were intending, I suspect.

foreach ( @list ) {
$n = index($_, /$tag/i);

This isn't doing what you intended either. The pattern match will
return either 1 or 0 depending on if a match is found, which will then
be passed as the 2nd argument to index().

Perhaps you meant something like:
return 1 if index $_ , $tag;
or
return 1 if /$tag/;

I'm not really sure what your my_index() function is trying to achieve
though. Use grep() if you are trying to deterine the existence of
something within a list.
 
K

Klaus Eichner

Mark said:
Hi all,

I tried to find the way to search the first occurence of a string into
a list (which is a sub-set of a file) in order to know if this string
occurs at least one time anywhere.
[...]

I tried something like the following, but it seems that I do not handle
properly the line I passed to the function:
[...]

$count = &my_index ("$i",@f_lines) ;

I don't think this is a problem, but it would be a better style not to use
quotes in "$i".

[...]
sub my_index() {
# $_[0]: searched string
# $_[1]: list

my $tag = $_[0];
my @list = $_[1];

Here is a problem:
In your program, the parametr "@f_lines" of the function call "&my_index
("$i",@f_lines);" will always be flattened, such that $_[0] = $i, $_[1] =
$f_lines[0], $_[2] = $f_lines[1], $_[3] = $f_lines[2], etc...

So assigning $_[1] to @list only gets you the first element of @f_lines.

I suggest you get the other elements ($_[2] = $f_lines[1], $_[3] =
$f_lines[2], etc...) as well, for example:

sub my_index() {
my $tag = shift;
my @list = @_;
 
T

Tad McClellan

Mark said:
I tried to find the way to search the first occurence of a string into
a list (which is a sub-set of a file) in order to know if this string
occurs at least one time anywhere.

I've read the perldoc -f grep and perldoc -f index


See also your FAQ:

perldoc -q list

How can I tell whether a certain element is contained in a list or array?
 

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
473,995
Messages
2,570,236
Members
46,822
Latest member
israfaceZa

Latest Threads

Top