0

If using the 'csv' library in ruby, how would you replace the headers without re-reading in a file?

foo.csv

'date','foo',bar'
1,2,3
4,5,6

Using a CSV::Table because of this answer

Here is a working solution, however it requires writing and reading from a file twice.

require 'csv'
@csv = CSV.table('foo.csv')

# Perform additional operations, like remove specific pieces of information. 

# Save fixed csv to a file (with incorrect headers)
File.open('bar.csv','w') do |f|
  f.write(@csv.to_csv)
end

# New headers
new_keywords = ['dur','hur', 'whur']

# Reopen the file, replace the headers, and print it out for debugging
# Not sure how to replace the headers of a CSV::Table object, however I *can* replace the headers of an array of arrays (hence the file.open)
lines = File.readlines('bar.csv')
lines.shift
lines.unshift(new_keywords.join(',') + "\n")
puts lines.join('')

# TODO: re-save file to disk

How could I modify the headers without reading from disk twice?

'dur','hur','whur'
1,x,3
4,5,x

Update
For those curious, here is the unabridged code. In order to use things like delete_if() the CSV must be imported with the CSV.table() function.

Perhaps the headers could be changed by converting the csv table into an array of arrays, however I'm not sure how to do that.

4
  • 1
    In your example you're reading one csv, writing to another, reading the second another time and eventually printing it all as a string. Do you want the exact same content just with different headers? Is the desired output the last snippet? Commented Nov 5, 2014 at 2:51
  • I've added some code comments that should clarify this better. I'm trying to replace "date","foo","bar" with "dur","hur","whur" in a less clunky manor. Commented Nov 5, 2014 at 2:58
  • 1
    why not in the initial read of the file, skip the headers with headers: true and just write what you want the headers to be in the new csv? Commented Nov 5, 2014 at 3:17
  • I am doing some operations on the csv table that require knowing what the headers are. Commented Nov 5, 2014 at 4:07

1 Answer 1

1

Given a test.csv file whose contents look like this:

id,name,age
1,jack,8
2,jill,9

You can replace the header row using this:

require 'csv'

array_of_arrays = CSV.read('test.csv')

p array_of_arrays # => [["id", "name", "age"],
                  # =>  ["1", "jack", "26"],
                  # =>  ["2", "jill", "27"]]    

new_keywords = ['dur','hur','whur']

array_of_arrays[0] = new_keywords

p array_of_arrays # => [["dur", "hur", "whur"],
                  # =>  ["1", " jack", " 26"],
                  # =>  ["2", " jill", " 27"]]

Or if you'd rather preserve your original two-dimensional array:

new_array = Array.new(array_of_arrays)
new_array[0] = new_keywords

p new_array # => [["dur", "hur", "whur"],
            # =>  ["1", " jack", " 26"],
            # =>  ["2", " jill", " 27"]]

p array_of_arrays # => [["id", "name", "age"],
                  # =>  ["1", "jack", "26"],
                  # =>  ["2", "jill", "27"]]
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, however the code is already using CSV.table() so that the headers are created a symbols, thus allowing the use of delete_if(). Can this be done with CSV.table() github.com/spuder/simple-ynab/blob/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.