CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
stuck in doing multiple condition in IF statement

 



shinova
Novice

Sep 8, 2010, 7:40 AM

Post #1 of 8 (1159 views)
stuck in doing multiple condition in IF statement Can't Post

Hi guys,

I'm trying to do a search program which searches books through a text file which contain lots of books information. Basically the text file contain about 29 types of information, such as ISBN, title, author, price.. etc.. of the book.

Code
#snippet of the text file 
...
"publication_date" : "2009-02-17",
"edition" : "Reprint",
"isbn" : "1401322638",
"dewey_decimal" : "813",
"authors" : [
"John Deo"
],
"Binding" : "Paperback",
"SalesRank" : "184417",
"Catalog" : "Book",
"price" : "$15.99",
...



Below is the example usage to run the perl program:

Code
input: perl book_search.pl books.text publisher:John title:Apple


Below is a snippet of my code right now BUT only limits up to 2 types of parameter.

Basically I'm splitting all the input arguments accordingly and store it in two separate arrays.

Code
@paramArray = (); 
@searchArray = ();


for ($i=1; $i <@ARGV; $i++){
($param) = split m/:/, $ARGV[$i];
$search_key = substr($ARGV[$i],(rindex($ARGV[$i],":")+1));
push(@paramArray, $param);
push(@searchArray, $search_key);
}


Then I pass the array values to here, based on the array size, which determines the number of input parameters and do the search.

Code
sub print_search_books() { 
my @sorted_isbns = sort by_price keys %books;
$paramLength = @paramArray;

if($paramLength < 2){
if($books{$isbn}{$param} =~ m/\b$search_key\b/i){
printf "%s %7s %s - %s\n", $isbn, $books{$isbn}{price}, $books{$isbn}{title},
join(', ', @{$books{$isbn}{authors}});
}
}
elsif($paramLength == 2){
if($books{$isbn}{$paramArray[0]} =~ m/\b$searchArray[0]\b/ && $books{$isbn}{$paramArray[1]} =~ m/\b$searchArray[1]\b/){
printf "%s %7s %s - %s\n", $isbn, $books{$isbn}{price}, $books{$isbn}{title},
join(', ', @{$books{$isbn}{authors}});
}
}
}


My code is running fine right now. However, my problem now is that, if I want to use more than 2 input parameters, or rather to use all 29 parameters to search for example:

Code
input: perl book_search.pl books.text publisher:John title:Apple isbn:1234567890 Catalog:Book year:2009 etc...


How can I do that, OTHER than to do elsif($paramLength == 2){} X29 times....

I appreciate if anyone could help.

Cheers,
shinova


(This post was edited by shinova on Sep 8, 2010, 7:57 AM)


BillKSmith
Veteran

Sep 8, 2010, 1:43 PM

Post #2 of 8 (1140 views)
Re: [shinova] stuck in doing multiple condition in IF statement [In reply to] Can't Post

I am not sure how you store your data. I think it is a list of hashes (one hash for each book). For each parameter, use grep to remove from the list, all the books that do not match. There is no limit to how many times you can do this. The surviving book(s) is(are) the desired result.



A more professional approach would be to store your data in a commercial data base rather than a text file. Your application could then querry it using a module such as DBI.
Good Luck,
Bill


shinova
Novice

Sep 8, 2010, 6:13 PM

Post #3 of 8 (1128 views)
Re: [BillKSmith] stuck in doing multiple condition in IF statement [In reply to] Can't Post

yup, my data are stored in list of hashes.

Code
... 
open BOOKS_FILE, "<$ARGV[0]" or die "$0: can not open '$ARGV[0]': $!\n";
while ($line = <BOOKS_FILE>) {
if ($line =~ /^\s*"(\d+X?)"\s*:\s*{\s*$/) {
$current_isbn = $1;
}
elsif ($line =~ /^\s*"title"\s*:\s*"(.*)",?\s*$/i) {
$books{$current_isbn}{title} = $1;
}
elsif ($line =~ /^\s*"price"\s*:\s*"(.*)",?\s*$/) {
$books{$current_isbn}{price} = $1;
}
...



BillKSmith
Veteran

Sep 8, 2010, 9:19 PM

Post #4 of 8 (1118 views)
Re: [shinova] stuck in doing multiple condition in IF statement [In reply to] Can't Post

Your code disagrees with your text. The variable %books is a hash of hashes. The keys are the isbn's. Isbn is therefore special. If it is specified, you can access all the data for that book.

You can already select a book if one or two of the other parameters are specified. You want this generalized to any number of parameters. Not a bad approach. Sorry I do not have time to work on it tonight.
Good Luck,
Bill


1arryb
User

Sep 9, 2010, 6:58 AM

Post #5 of 8 (1096 views)
Re: [shinova] stuck in doing multiple condition in IF statement [In reply to] Can't Post

Hi shinova,

This is kind of a monstrous way to search, but one idea that
comes to mind is to always load your parameters and search
terms into the arrays, even if there's only one each. Then,
search in a loop on @paramArray. That way, it doesn't matter
how many there are.

Code
# Untested snippet. 
# Shinova, Read BillK's comment about code disagreement.
...
my $found = 1;
for (my $i = 0; $i < scalar(@paramAarray); $i++) {
unless ($books{$isbn}{$paramArray[$i]} =~ m/\b$searchArray[$i]\b/i) {
$found = 0;
last;
}
}
if ( $found ) {
printf "%s %7s %s - %s\n", $isbn, $books{$isbn}{price}, $books{$isbn}{title},
join(', ', @{$books{$isbn}{authors}});
}
...

Cheers,

Larry


(This post was edited by 1arryb on Sep 9, 2010, 7:02 AM)


shinova
Novice

Sep 9, 2010, 8:02 AM

Post #6 of 8 (1091 views)
Re: [1arryb] stuck in doing multiple condition in IF statement [In reply to] Can't Post

Hi Larry,

Once again thank you so much for your reply. Yea totally agree with you and BillK's comments, the more if-else statement I code, the more disastrous it is.

Anyway I already re-do the codes and is somewhat similar to yours and it works!

I initialized a $books{$current_isbn}{match} = "yes"; while gathering all the information from the book.

Code
		elsif ($line =~ /^\s*"publisher"\s*:\s*"(.*)",?\s*$/i) { 
$books{$current_isbn}{publisher} = $1 if $1;
$books{$current_isbn}{match} = "yes" if $1;
}
elsif ($line =~ /^\s*"isbn"\s*:\s*"(.*)",?\s*$/i) {
$books{$current_isbn}{isbn} = $1 if $1;
$books{$current_isbn}{match} = "yes" if $1;
}


then flag the value to "no" if there's no match.

Code
..... 
if($books{$isbn}{$search_term} !~ m/\b$search_key\b/i){

$books{$isbn}{match} = "no";

}
.....


and then print out if is a 'yes'.

Code
... 
if($books{$isbn}{match} eq "yes"){
#print out
}
...


I reckon you style is much neater.

However, there still a small problem when searching for the author's field.
Because the authors field is in a list and is in stored in an array like this:

Code
		elsif ($line =~ /^\s*"isbn"\s*:\s*"(.*)",?\s*$/i) { 
$books{$current_isbn}{isbn} = $1 if $1;
$books{$current_isbn}{match} = "yes" if $1;
}
elsif ($line =~ /"authors"/) {
$books{$current_isbn}{authors} = [];
for(;;){
$line = <BOOKS_FILE>;
last unless defined($line);
last if $line =~ /]/;
$line =~ /"(.+)"/;
push(@{$books{$current_isbn}{authors}}, $1) if $1;
}
}


I can't do a match like this to check the authors' array because authors is being stored differently.

Code
..... 
#@{$books{$isbn}{authors}}

if($books{$isbn}{$search_term} !~ m/\b$search_key\b/i){
$books{$isbn}{match} = "no";
}
.....


what I can think of is unless if the user input contains a "authors" parameter, for example:

Code
input: perl search3.pl books.txt publisher:Media title:Perl authors:John


then i will do another if-condition statement something like this just to cater for author.

Code
..... 
if("@{$books{$isbn}{authors}}" !~ m/\b$search_key\b/i){
...
}
......


but I really hope to avoid too many if-conditions. Is there any other better way to check the authors field?


Cheers,
shinova


(This post was edited by shinova on Sep 9, 2010, 8:08 AM)


1arryb
User

Sep 9, 2010, 9:07 AM

Post #7 of 8 (1077 views)
Re: [shinova] stuck in doing multiple condition in IF statement [In reply to] Can't Post

Hi shinova,

You know the authors member is a list so you can always do something special for this parameter.
Also, thinking about it, I was being stupid about my loop. Better to start with $found = 0 and abort
the loop if we actually match something (d'oh!).

As an aside, I still think you'd be better off using references instead of true hashes/arrays for you books structure:

Code
# Untested snippet. 
...
my $found = 0;
for (my $i = 0; $i < scalar(@paramAarray); $i++) {
if ( $paramArray[$i] eq 'authors' ) {
$found = 1 unless grep(/\b$searchArray[$i]\b/i, @{$books{$isbn}{$paramArray[$i]}};
} else {
$found = 1 unless $books{$isbn}{$paramArray[$i]} =~ m/\b$searchArray[$i]\b/i;
}
last if $found;
}
if ( $found ) {
printf "%s %7s %s - %s\n", $isbn, $books{$isbn}{price}, $books{$isbn}{title},
join(', ', @{$books{$isbn}{authors}});
}
...

Cheers,

Larry


shinova
Novice

Sep 10, 2010, 1:35 AM

Post #8 of 8 (1064 views)
Re: [1arryb] stuck in doing multiple condition in IF statement [In reply to] Can't Post

Hi Larry,

Thanks alot for the advice. Everything seems fine now. I really appreciate your help!~

Cheers,
shinova

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives