Parsing a CSV file having multiple records in RUBYp

K

Krishna Mundra

Hi everyone,

Can anyone help me in parsing a CSV file,with comma seperated multiple
records (multiple columns and multiple rows)....


What i am doing is

uploading a CSV file and reading the records from CSV file,first row
contains field names(database field names),reaing record line by line
and splitting each record by a comma(since CSV file is a comma seperated
fields)
and sending the splitted data into corresponding fields of database.

everything goes well except last column of the record is skipping in my
logic.

My logic unable to read the last field values and field name.If I put an
extra

column name,my logic is working well and good.

here is my logic.....
rows=Array.new
columns=Array.new
physician= Physician.new // object of physician in to which values are
send after spilltting.
File.open(@filepath, "r") do |f|
f.each_line { |line|
if(count==0)
header=line.to_s
columns=header.split(',')
end
else
str=line.to_s
rows=str.split(',')
columns.each do |col|
physician[columns[cnt]]= rows[cnt]
cnt=cnt+1
end
end

Can anyone solve my problem,Its urgent
 
W

Wild Karl-Heinz

In message "Parsing a CSV file having multiple records in RUBYp"

KM> Can anyone help me in parsing a CSV file,with comma seperated multiple
KM> records (multiple columns and multiple rows)....

/usr/local/lib/ruby/1.8/csv.rb

maybe it helps.

regards.
Karl-Heinz
 
C

come

Hi,

The ruby standard library include a CSV parser (you will find the api
there : http://www.ruby-doc.org/stdlib/). You should try it.

require 'csv'
CSV.open(@filepath, "r") do |csv|
# csv[0]..csv[n] contains your columns...
end

Since your file has a header, you could write something like :

require 'csv'
my_csv = CSV.open(@filepath, "r")
header = my_csv.shift # header is a array containing each column of
your first line
my_csv.each do |row|
row.each_index { |i| physician[header] = row }
end
my_csv.close

.... But be carrefull if your file contains more than one line and you
didn't overload the "=" operator of physician because you will affect
all lines in the same physician object...

Krishna Mundra a écrit :
 
J

James Edward Gray II

Since your file has a header, you could write something like :

Obviously I am biased, but I sure think FasterCSV makes this kind of
thing easier:
item,in_stock,reorder_limit
"Real ""Rubies""",10,5
Pearls,100,20
Snakes,2,5
END_CSV
=> "item,in_stock,reorder_limit\n"Real ""Rubies""",10,5\nPearls,100,20
\nSnakes,2,5\n"=> :symbol)
=> #<FasterCSV::Table:0x6e570c @mode=:col_or_row, @table=
[#<FasterCSV::Row:0x6e5310 @header_row=false, @row=[[:item, "Real
\"Rubies\""], [:in_stock, "10"], [:reorder_limit, "5"]]>,
#<FasterCSV::Row:0x6e4f00 @header_row=false, @row=[[:item, "Pearls"],
[:in_stock, "100"], [:reorder_limit, "20"]]>, #<FasterCSV::Row:
0x6e4af0 @header_row=false, @row=[[:item, "Snakes"], [:in_stock,
"2"], [:reorder_limit, "5"]]>]readline require__ result
readlines require_gem retry
redo require_gem_with_options return
remove_instance_variable rescue
require respond_to?
puts result.map { |row| row[:item] }
Real "Rubies"
Pearls
Snakes
=> nil{:in_stock=>"10", :reorder_limit=>"5", :item=>"Real \"Rubies\""}
{:in_stock=>"100", :reorder_limit=>"20", :item=>"Pearls"}
{:in_stock=>"2", :reorder_limit=>"5", :item=>"Snakes"}
=> #<FasterCSV::Table:0x6e570c @mode=:col_or_row, @table=
[#<FasterCSV::Row:0x6e5310 @header_row=false, @row=[[:item, "Real
\"Rubies\""], [:in_stock, "10"], [:reorder_limit, "5"]]>,
#<FasterCSV::Row:0x6e4f00 @header_row=false, @row=[[:item, "Pearls"],
[:in_stock, "100"], [:reorder_limit, "20"]]>, #<FasterCSV::Row:
0x6e4af0 @header_row=false, @row=[[:item, "Snakes"], [:in_stock,
"2"], [:reorder_limit, "5"]]>]

James Edward Gray II
 
M

matt

James,

Not to be off topic, but how did you get an 'auto complete' type shell ?

I tried it at home and it didn't do what your output shows.... I'm
jealous.

It almost looks like you overloaded puts ...

Is there a big secret to share? I'd even settle of a little secret.
I'm not picky!

Matt


readline require__ result
readlines require_gem retry
redo require_gem_with_options return
remove_instance_variable rescue
require respond_to?
puts result.map { |row| row[:item] }
 
C

côme

Hi,

You just start your line and press the tab key :

irb(main):001:0> toto=5
=> 5
irb(main):002:0> puts t[tab]
taint test throw to_s trace_var true
tainted? then to_a toto trap type
irb(main):002:0> puts toto.[tab]
toto.nil?
toto.__id__ toto.nonzero?
toto.__send__ toto.numerator
toto.abs toto.object_id
toto.between? toto.power!
toto.ceil toto.prec
toto.chr toto.prec_f
toto.class toto.prec_i
toto.clone toto.private_methods
toto.coerce toto.protected_methods
toto.denominator toto.public_methods
toto.display toto.quo
toto.div toto.rdiv
toto.divmod toto.remainder
toto.downto toto.require
toto.dup toto.require_gem
toto.eql? toto.respond_to?
toto.equal? toto.round
toto.extend toto.rpower
toto.floor toto.send
toto.freeze toto.singleton_method_added
toto.frozen? toto.singleton_methods
toto.gcd toto.size
--More--


matt a écrit :
 
W

William James

James said:
Since your file has a header, you could write something like :

Obviously I am biased, but I sure think FasterCSV makes this kind of
thing easier:
item,in_stock,reorder_limit
"Real ""Rubies""",10,5
Pearls,100,20
Snakes,2,5
END_CSV
=> "item,in_stock,reorder_limit\n"Real ""Rubies""",10,5\nPearls,100,20
\nSnakes,2,5\n"=> :symbol)
=> #<FasterCSV::Table:0x6e570c @mode=:col_or_row, @table=
[#<FasterCSV::Row:0x6e5310 @header_row=false, @row=[[:item, "Real
\"Rubies\""], [:in_stock, "10"], [:reorder_limit, "5"]]>,
#<FasterCSV::Row:0x6e4f00 @header_row=false, @row=[[:item, "Pearls"],
[:in_stock, "100"], [:reorder_limit, "20"]]>, #<FasterCSV::Row:
0x6e4af0 @header_row=false, @row=[[:item, "Snakes"], [:in_stock,
"2"], [:reorder_limit, "5"]]>]readline require__ result
readlines require_gem retry
redo require_gem_with_options return
remove_instance_variable rescue
require respond_to?
puts result.map { |row| row[:item] }
Real "Rubies"
Pearls
Snakes
=> nil{:in_stock=>"10", :reorder_limit=>"5", :item=>"Real \"Rubies\""}
{:in_stock=>"100", :reorder_limit=>"20", :item=>"Pearls"}
{:in_stock=>"2", :reorder_limit=>"5", :item=>"Snakes"}
=> #<FasterCSV::Table:0x6e570c @mode=:col_or_row, @table=
[#<FasterCSV::Row:0x6e5310 @header_row=false, @row=[[:item, "Real
\"Rubies\""], [:in_stock, "10"], [:reorder_limit, "5"]]>,
#<FasterCSV::Row:0x6e4f00 @header_row=false, @row=[[:item, "Pearls"],
[:in_stock, "100"], [:reorder_limit, "20"]]>, #<FasterCSV::Row:
0x6e4af0 @header_row=false, @row=[[:item, "Snakes"], [:in_stock,
"2"], [:reorder_limit, "5"]]>]

class String
def csv
(self + ",").scan(
/("(?:[^"]+|"")*"|[^,]*),/).flatten.
map{|s| s.gsub(/\A"|"\Z/,'').gsub(/""/,'"')}
end
end

data = DATA.readlines.map{|s| s.chomp.csv}
header = data.shift
p header
p data
puts
data.map{|a| header.zip(a).inject({}){|h,x|
h.merge({x[0].to_sym,x[1]}) }}.
each{|h| p h}

__END__
item,in_stock,reorder_limit
"Real ""Rubies""",10,5
Pearls,100,20
Snakes,2,5

--- output -----
["item", "in_stock", "reorder_limit"]
[["Real \"Rubies\"", "10", "5"], ["Pearls", "100", "20"], ["Snakes",
"2", "5"]]

{:in_stock=>"10", :reorder_limit=>"5", :item=>"Real \"Rubies\""}
{:in_stock=>"100", :reorder_limit=>"20", :item=>"Pearls"}
{:in_stock=>"2", :reorder_limit=>"5", :item=>"Snakes"}
 

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,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top