Kristada673
Kristada673

Reputation: 3744

How to use CSV.open and CSV.foreach methods to convert specific data in a csv file?

The Old.csv file contains these headers, "article_category_id", "articleID", "timestamp", "udid", but some of the values in those columns are strings. So, I am trying to convert them to integers and store in another CSV file, New.csv. This is my code:

require 'csv'
require 'time'

CSV.foreach('New.csv', "wb", :write_headers=> true, :headers =>["article_category_id", "articleID", "timestamp", "udid"]) do |csv|
    CSV.open('Old.csv', :headers=>true) do |row|

        csv['article_category_id']=row['article_category_id'].to_i
        csv['articleID']=row['articleID'].to_i
        csv['timestamp'] = row['timestamp'].to_time.to_i unless row['timestamp'].nil?

        unless udids.include?(row['udid'])
          udids << row['udid']
        end
        csv['udid'] = udids.index(row['udid']) + 1

        csv<<row
    end
end

But, I am getting the following error: in 'foreach': ruby wrong number of arguments (3 for 1..2) (ArgumentError).

When I change the foreach to open, I get the following error: undefined method '[]' for #<CSV:0x36e0298> (NoMethodError). Why is that? And how can I resolve it? Thanks.

Upvotes: 5

Views: 9362

Answers (3)

sonar0007
sonar0007

Reputation: 86

The problem with Vinh answer is that at the end array variable is an array which has array inside. So what is inserted indo CVS looks like [[article_category_id, articleID, timestamp, udid]] And that is why you get results in double quotes.

Please try something like this:

require 'csv'
require 'time'

CSV.open('New.csv', "wb") do |csv|
  csv << ["article_category_id", "articleID", "timestamp", "udid"]
  CSV.foreach('Old.csv', :headers=>true) do |row|
    article_category_id = row['article_category_id'].to_i
    articleID = row['articleID'].to_i
    timestamp = row['timestamp'].to_i unless row['timestamp'].nil?

    unless udids.include?(row['udid'])
      udids << row['udid']
    end
    udid = udids.index(row['udid']) + 1
    output_row = [article_category_id, articleID, timestamp, udid]

    csv << output_row
  end
end

Upvotes: 0

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 120990

CSV#foreach does not accept file access rights as second parameter:

CSV.open('New.csv', :headers=>true) do |csv|
  CSV.foreach('Old.csv',
    :write_headers => true, 
    :headers => ["article_category_id", "articleID", "timestamp", "udid"]
  ) do |row|
    row['article_category_id'] = row['article_category_id'].to_i
    ...
    csv << row
  end
end

CSV#open should be placed before foreach. You are to iterate the old one and produce the new one. Inside the loop you should change row and than append it to the output.

Upvotes: 4

Vincent Nguyen
Vincent Nguyen

Reputation: 311

You can refer my code:

require 'csv'
require 'time'

CSV.open('New.csv', "wb") do |csv|
  csv << ["article_category_id", "articleID", "timestamp", "udid"]
  CSV.foreach('Old.csv', :headers=>true) do |row|
    array = []
    article_category_id=row['article_category_id'].to_i
    articleID=row['articleID'].to_i
    timestamp = row['timestamp'].to_i unless row['timestamp'].nil?

    unless udids.include?(row['udid'])
      udids << row['udid']
    end
    udid = udids.index(row['udid']) + 1
    array << [article_category_id, articleID, timestamp, udid]

    csv<<array
  end
end

Upvotes: 0

Related Questions