5

I am using FasterCSV and i am looping with a foreach like this

FasterCSV.foreach("#{Rails.public_path}/uploads/transfer.csv", :encoding => 'u', :headers => :first_row) do |row|

but the problem is my csv has the first 3 lines as the headers...any way to make fasterCSV skip the first three rows rather then only the first??

Matt Elhotiby
  • 43,028
  • 85
  • 218
  • 321

3 Answers3

19

Not sure about FasterCSV, but in Ruby 1.9 standard CSV library (which is made from FasterCSV), I can do something like:

c = CSV.open '/path/to/my.csv'
c.drop(3).each do |row|
  # do whatever with row
end
Mladen Jablanović
  • 43,461
  • 10
  • 90
  • 113
  • where are you finding the drop function ...here is the documentation and i dont see drop http://www.ruby-doc.org/stdlib/libdoc/csv/rdoc/index.html – Matt Elhotiby Sep 07 '11 at 21:53
  • @Tamer, since c is of type array you can use the drop method to return the same array without the first 3 rows. http://www.ruby-doc.org/core/classes/Array.html – Jason Slocomb Sep 08 '11 at 01:15
  • 3
    @Tamer: `c` is not an Array, but `CSV` class includes `Enumerable` module, and it automagically brings in bunch of methods, `drop` being one of them. http://www.ruby-doc.org/core/classes/Enumerable.html#M001520 – Mladen Jablanović Sep 08 '11 at 06:17
  • You are awesome.. Really really awesome. Way to do it right! – baash05 May 28 '12 at 23:18
5

I'm not a user of FasterCSV, but why not do the control yourself:

additional_rows_to_skip = 2
FasterCSV.foreach("...", :encoding => 'u', :headers => :first_row) do |row|
    if additional_rows_to_skip > 0
        additional_rows_to_skip -= 1
    else
        # do stuff...
    end
end
Joaquim Rendeiro
  • 1,388
  • 8
  • 13
  • seriously? you have a 300 page book and you're not interested in the first three pages. Each time you turn the page, ask yourself out loud, "Am I skipping this page.". Then again, "Am I skipping this page?", Then again, "Am I skipping this page?". OrderN extra compares, seems fine to far to many modern programmers. – baash05 May 28 '12 at 23:17
  • 4
    @daveatflow: Actually, `drop` has to use counter internally as well. Also, `drop` returns an Array, which may not be always desirable (say, if used with huge files). So, nothing wrong with this solution (except for not being elegant), certainly doesn't deserve a downvote. Cheers. – Mladen Jablanović May 29 '12 at 08:51
0

Thanks to Mladen Jablanovic. I got my clue.. But I realized something interesting In 1.9, reading seems to be from POS. In this I mean if you do

c = CSV.open iFileName
logger.debug c.first
logger.debug c.first
logger.debug c.first

You'll get three different results in your log. One for each of the three header rows.
c.each do |row| #now seems to start on the 4th row.

It makes perfect sense that it would read the file this way. Then it would only have to have the current row in memory.

I still like Mladen Jablanovićs answer, but this is an interesting bit of logic too.

baash05
  • 4,394
  • 11
  • 59
  • 97