Reputation: 13285
I have following CSV data:
10,11,12.34
I can parse this using CSV from the standard library, and have the values converted from strings to numbers:
require 'csv'
CSV.parse( "10,11,12.34" )
=> [["10", "11", "12.34"]]
CSV.parse( "10,11,12.34", {:converters => [:integer,:integer,:float]} )
=> [[10, 11, 12.34]]
I don't want to convert column 1, I'd just like that left as a string. My guess was I could omit a value from the converters array, but that didn't work:
CSV.parse( "10,11,12.34", {:converters => [nil,:integer,:float]} )
NoMethodError: undefined method `arity' for nil:NilClass
from /home/ian/.rvm/rubies/jruby-1.6.6/lib/ruby/1.9/csv.rb:2188:in `convert_fields'
from org/jruby/RubyArray.java:1614:in `each'
from /home/ian/.rvm/rubies/jruby-1.6.6/lib/ruby/1.9/csv.rb:2187:in `convert_fields'
from org/jruby/RubyArray.java:2332:in `collect'
from org/jruby/RubyEnumerator.java:190:in `each'
from org/jruby/RubyEnumerator.java:404:in `with_index'
from /home/ian/.rvm/rubies/jruby-1.6.6/lib/ruby/1.9/csv.rb:2186:in `convert_fields'
from /home/ian/.rvm/rubies/jruby-1.6.6/lib/ruby/1.9/csv.rb:1923:in `shift'
from org/jruby/RubyKernel.java:1408:in `loop'
from /home/ian/.rvm/rubies/jruby-1.6.6/lib/ruby/1.9/csv.rb:1825:in `shift'
from /home/ian/.rvm/rubies/jruby-1.6.6/lib/ruby/1.9/csv.rb:1767:in `each'
from org/jruby/RubyEnumerable.java:391:in `to_a'
from /home/ian/.rvm/rubies/jruby-1.6.6/lib/ruby/1.9/csv.rb:1778:in `read'
from /home/ian/.rvm/rubies/jruby-1.6.6/lib/ruby/1.9/csv.rb:1365:in `parse'
from (irb):25:in `evaluate'
In fact I haven't been able to find any way of specifying that I'd like the first column to be left unconverted. Any suggestions?
Update
I think I misunderstood the design intention for :converters
. It's not a 1:1 mapping by column, but a list of converters to be applied (I think) to all values. I'm not sure, the docs aren't too clear. So the more general question is: How do I convert some columns in my CSV, and not others?
Upvotes: 3
Views: 1685
Reputation: 211540
The documentation says these options aren't specified per column, but are instead a list of converters that will be applied to all columns.
Example:
CSV.parse("10,11,13,12.34", { :converters => [lambda{|s|s.to_s + 'x'}] })
# => [["10x", "11x", "13x", "12.34x"]]
Since the CSV module is eager to convert everything it can, you may as well shift back any columns you want using .to_s
or use the :unconverted_fields
option to save the original values and allow access to them.
Upvotes: 1