Parsing a CSV file having multiple records in RUBYp

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

···

--
Posted via http://www.ruby-forum.com/.

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

maybe it helps.

regards.
Karl-Heinz

···

In message "Parsing a CSV file having multiple records in RUBYp" on 26.12.2006, Krishna Mundra <krishna_mundra82@rediffmail.com> writes:

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

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[i]] = row[i] }
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 :

···

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

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:

>> require "rubygems"
=> false
>> require "faster_csv"
=> true
>> csv = <<END_CSV
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"
>> result = FCSV.parse(csv, :headers => true, :header_converters => :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"]]>]
>> puts re
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
>> result.each { |row| p row.to_hash }
{: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

···

On Dec 26, 2006, at 3:15 AM, come wrote:

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

···

On Wed, 2006-12-27 at 00:30 +0900, James Edward Gray II wrote:

>> puts re
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] }

James Edward Gray II wrote:

> 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:

>> require "rubygems"
=> false
>> require "faster_csv"
=> true
>> csv = <<END_CSV
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"
>> result = FCSV.parse(csv, :headers => true, :header_converters
=> :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"]]>]
>> puts re
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
>> result.each { |row| p row.to_hash }
{: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"}

···

On Dec 26, 2006, at 3:15 AM, come wrote:

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 :

···

James,

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

http://wiki.rubygarden.org/Ruby/page/show/Irb/TipsAndTricks

:wink:

James Edward Gray II

···

On Dec 26, 2006, at 11:09 AM, matt wrote:

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!