Searching a CSV file - beginner seeking help

S

Simon Harrison

Hi all. I've written a little script to search a csv file for films. It
works but has problems. I'd appreciate any pointers with the following:

1. I've used instance variables without a class, to make them visible
amongst methods. Is this acceptable for a short script like this?

2. As it is, it will only match exactly. For example, I have The Mummy
and The Mummy Returns. If I search for 'mummy' program reports "film not
found." I know I need to use Regexp's, not sure how to implement it here
though.

3. Any other comments gratefully received.


#################
# search_films.rb
#################

require 'csv'

def load_xvid_file(path_to_csv)
@names = []
csv_contents = CSV.read(path_to_csv)
csv_contents.shift
csv_contents.each do |row|
@names << row[0]
end
@names.each { |f| f.downcase! }
end

def search_for_film
print "Enter name of film to search for: "
film = gets.chomp.downcase
puts

if @names.include?(film)
puts "#{film} found!"
else
puts "#{film} not found :("
end
prompt
end

def prompt
print "Search again? (y or n) "
answer = gets.chomp.downcase

case answer
when /y/
search_for_film
when /n/
puts "Goodbye."
exit
else
prompt
end
end

load_xvid_file("/home/simon/Documents/CSV/XviD.csv")
search_for_film
 
S

Simon Harrison

Sorry, don't know your name. You're just appearing as 'guest'. Are you
sure it's a good idea to have globals in block variables? I've been
continuing to play and the following seems to be what I'm after. Sadly
nothing prints out and the program exits.


def search_for_film
print "Enter name of film to search for: "
film = gets.chomp.downcase

results = @films.grep(/film/)
if results
print results
elsif results.empty?
puts "Nothing found."
else
menu
end
end


Here is irb demonstrating that it *should* work!


irb(main):009:0> films = ['the mummy', 'the mummy returns', 'the mummy
7', 'the daddy']
=> ["the mummy", "the mummy returns", "the mummy 7", "the daddy"]
irb(main):010:0> films.grep(/mummy/)
=> ["the mummy", "the mummy returns", "the mummy 7"]
irb(main):011:0>
 
S

Simon Harrison

Got it!

def search_for_film
print "Enter name of film to search for: "
film = gets.chomp.downcase

results = @films.grep(/#{film}/)
if results
puts results
menu
elsif results.empty?
puts "Nothing found."
menu
else
menu
end
end
 
S

Simon Harrison

This works perfectly for me now. In case anyone may benefit from it:


require 'csv'

def load_xvid_file(path_to_csv)
@films = []
csv_contents = CSV.read(path_to_csv)
csv_contents.shift
csv_contents.each do |row|
@films << row[0]
end
@films.each { |f| f.downcase! }
end

def search_for_film
print "Enter name of film to search for: "
film = gets.chomp.downcase

results = [@films.grep(/#{film}/)]
if results
results.each { |f| puts f }
prompt
else
puts "Nothing found."
prompt
end
end

def prompt
print "Search again? (y or n) "
answer = gets.chomp.downcase

case answer
when /^y/
search_for_film
when /^n/
puts "Goodbye."
exit
else
prompt
end
end

load_xvid_file("/home/simon/Documents/CSV/XviD.csv")
search_for_film
 
J

Jesús Gabriel y Galán

This works perfectly for me now. In case anyone may benefit from it:


require 'csv'

def load_xvid_file(path_to_csv)
=A0@films =3D []
=A0csv_contents =3D CSV.read(path_to_csv)
=A0csv_contents.shift
=A0csv_contents.each do |row|
=A0 =A0@films << row[0]
=A0end
[email protected] { |f| f.downcase! }
end

def search_for_film
=A0print "Enter name of film to search for: "
=A0film =3D gets.chomp.downcase

=A0results =3D [@films.grep(/#{film}/)]
=A0if results

this will always be true, since you are initializing results to an
array. Enumerable#grep already returns an array, so I'd do:

results =3D @films.grep(/#{film}/)
if results.empty?
puts "nothing found"
else
results.each ...


if results
=A0 =A0results.each { |f| puts f }
=A0 =A0prompt
=A0else
=A0 =A0puts "Nothing found."
=A0 =A0prompt
=A0end
end

def prompt
=A0print "Search again? (y or n) "
=A0answer =3D gets.chomp.downcase

=A0case answer
=A0when /^y/
=A0 =A0search_for_film
=A0when /^n/
=A0 =A0puts "Goodbye."
=A0 =A0exit
=A0else
=A0 =A0prompt
=A0end
end

load_xvid_file("/home/simon/Documents/CSV/XviD.csv")
search_for_film

By the way, I'd change a bit around the logic and the user interface,
you seem to have both a little bit mixed up. I would call method
prompt from the main script, in that method I would ask the user for a
word and call search_for_film passing what the user typed. From that
method I would return the results array. Back in the prompt method, I
would print the results and loop for another run. This way,
search_for_film is not tied to the specific user interaction and is
more general and easier to refactor and reuse.

Jesus.
 
S

Simon Harrison

Thanks marco. Looks like it has potential. I can't think how it would
really help me with this little project but thanks for the link.
 

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,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top