Ian Dickinson
Ian Dickinson

Reputation: 13285

Ruby 1.9 CSV: selectively ignoring conversions for a column

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

Answers (1)

tadman
tadman

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

Related Questions