Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations derfloh on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

searching through files...

Status
Not open for further replies.

perlone

Programmer
Joined
May 20, 2001
Messages
438
Location
US
Hi,

I have a file called items.txt and it has the following things:

Gym License
Fishing License
Game License

How do I search through this file to find out to see if the user has a gym license? Can any small search could do this? Thanks for your time.
 
A binary search would probably be the best route to take. The idea is that you have a sorted list, pick the middle element and see if it matches, is less than or is greater than the item you're searching for.. Then return or cut the search in half accordingly and try again. So we first read the file into an array and sort the array:
Code:
open(FH,$filename);
my @array = sort <FH>;
Then you initialize the boundaries of the array and a flag to activate if the item is found.
Code:
my ($l,$h) = (0,@array-1);
my $flag = 0;
Then start a loop that tries the middle element and resets one of the boundaries to the tried element +/- 1 if necessary (essentially cutting the array in half). This loop assumes the term you're searching for is in the $word variable.
Code:
while($l <= $h) {
    $_ = int(($l+h)/2);
    $l = $t+1, next if $array[$_] lt $word;
    $h = $t-1, next if $array[$_] gt $word;
    $flag = 1, last;
}
And you've found what you're looking for if($flag).

Hope this helps,

brendanc@icehouse.net
 
Just wanted to make a quick follow up to the binary search. That particular search is really only necessary when working with a large set of items to be searched. If you are working with a small list, you may find it more efficient to just go through the items from first element to last. ie:
Code:
open(FH,$filename);
my $flag = 0;

while(<FH>) {
    $flag = 1, last if $_ eq $word
}
Just a thought. Hope this helps.

brendanc@icehouse.net
 
:~/ Once again, gotta stop posting at 4am.
make that while statement:
Code:
while(<FH>) {
    $flag = 1, last if chomp($_) eq $word
}
I think you would want to chomp the $array[$_] in the binary search example as well.

An embarrassed brendanc@icehouse.net
 
Thanks again but I found really easy way:-):

open(F, &quot;items.cgi&quot;);
$items = <F>;
close(F);
$word = &quot;License&quot;;

if ($items =~ $word) {
#whoohoo! found one
}else{
#nope
}



 
That particular method will only check the first item in your list.. So if you have:

Gym License
Fishing License

And try to match &quot;Fishing&quot;, you'll be given a false value.

If you assign the filehandle to an array type rather than a scalar, you get each line of the file stored in different elements of the array which makes while (or foreach)-loop matching the way to go.

Hope this helps,

brendanc@icehouse.net

PS. Wanted to make yet another change to the binary search above. Every instance of $t should be $_.
 
AaronGeorg,

When you read in from a text file you read line by line. If you wanted to go the string route that you tried and only get the first line, you could try doing this.

local $/;
$/=undef;

This is the line seperator. The default is the new line. That way, you just read in the first line. In the above, you can undef the line seperator, passing in the whole file into the string. Then you can do your reg. exp. Unfortunately, doing your pattern match on license will yield a true because you have more than one license in the string. So you may be searching for license, thinking you'd get gym license, and if the record doesn't have the gym one, it still may be true if there is another license. A pattern match on 'gym license' can work, but what if you have 'no gym license' or something that looks like the pattern but means the opposite.

I suggest opening the file handle and setting an array equal to the file handle, as suggested by others.

@array=<filehandle>;
foreach my $array(@array){

#this match should yield only gym license on the line.
if ($array=~/^gym license\n$/i){
####do your stuff here
}
}

Hope this helps.

Mike
 
AaronGeorge,

Just a quick follow up using $/;
my $filedata;
{
local $/;
$/=undef;
$filedata=<FILEHANDLE>;
}

Just wanted to show you that you should localize that $/ to be just for $filedata, or whatever you name the scalar that gets the input from the file. You may be opening files later and you may want the line seperator $/ back to breaking at new lines.

Mike
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top