Also, even in these trivial examples, I sure think that the code which
uses FasterCSV is pretty, even if I'm using the likely-to-be-slowest
form of generating rows in the library...
Writing CSV is very easy (unlike reading it correctly). FasterCSV
uses something close to the code shown in this thread, though William
James and I obviously disagree about the CSV format. Here's the code
from the library:
@io << row.map do |field|
if field.nil? # represent +nil+ fields as empty unquoted fields
""
else
field = String(field) # Stringify fields
# represent empty fields as empty quoted fields
if field.empty? or field.count(%Q{\r\n#{@col_sep}"}).nonzero?
%Q{"#{field.gsub('"', '""')}"} # escape quoted fields
else
field # unquoted field
end
end
end.join(@col_sep) + @row_sep # add separators
If you want a lot of speed, use something like that directly. Ruby's
method calls are expensive and using the code directly shaves that off.
Of course, I still feel it is better to use the library, though I
appear to be outnumbered in that thinking these days.
100000.times { a.to_csv }
Just FYI, that's probably the slowest way to use FasterCSV to write
CSV, though it is my favorite too. Here's the implementation of
to_csv():
class Array
# Equivalent to <tt>FasterCSV::generate_line(self, options)</tt>.
def to_csv(options = Hash.new)
FasterCSV.generate_line(self, options)
end
end
As you can see, calling FasterCSV.generate_line() yourself saves a
layer of indirection.
If you are generating many lines and want to go as fast as possible
with the library use one of the following:
# to an IO...
FasterCSV.open(...) do |csv|
csv << [...]
csv << [...]
...
end
# to a String
FasterCSV.generate(...) do |csv|
csv << [...]
csv << [...]
...
end
I try not too loose too much sleep over optimizations like this until
I really need them though and I favor Array.to_csv() in my own code.
James Edward Gray II