如何使用FasterCSV更改CSV文件中的标题然后保存新标题?

时间:2009-06-02 17:21:16

标签: ruby fastercsv

我无法理解FasterCSV中的:header_converters和:转换器。基本上,我想要做的就是将列标题更改为适当的列名。

类似的东西:

FasterCSV.foreach(csv_file, {:headers => true, :return_headers => false, :header_converters => :symbol, :converters => :all} ) do |row|
    puts row[:some_column_header] # Would be "Some Column Header" in the csv file.

execpt我不理解:符号和:全部在转换器参数中。

3 个答案:

答案 0 :(得分:9)

:all转换器意味着它会尝试所有内置转换器,特别是:

:integer:   Converts any field Integer() accepts.
:float:     Converts any field Float() accepts.
:date:      Converts any field Date::parse() accepts.
:date_time: Converts any field DateTime::parse() accepts.

基本上,这意味着它会尝试将任何字段转换为这些值(如果可能),而不是将它们保留为字符串。因此,如果你执行row[i]并且它将返回String值'9',它将返回一个Integer值9。

标头转换器会更改标头用于索引行的方式。例如,如果做这样的事情:

FastCSV.foreach(some_file, :header_converters => :downcase) do |row|

您可以使用标题“Some Header”将列编入索引为row['some header']

如果您使用的是:symbol,则可以使用row[:some_header]对其进行索引。符号下标头名称,用下划线替换空格,并删除a-z,0-9和_以外的字符。它很有用,因为符号的比较远比字符串的比较快。

如果您想使用row['Some Header']索引列,那么就不要提供任何:header_converter选项。


编辑:

在回复你的评论时,我会害怕headers_convert不会做你想做的事。它不会更改标题行的值,只是它们如何用作索引。相反,您必须使用:return_headers选项,检测标题行并进行更改。要更改文件并再次将其写出,您可以使用以下内容:

require 'fastercsv'

input = File.open 'original.csv', 'r'
output = File.open 'modified.csv', 'w'
FasterCSV.filter input, output, :headers => true, :write_headers => true, :return_headers => true do |row|
  change_headers(row) if row.header_row?
end
input.close
output.close

如果您需要完全替换原始文件,请在执行上述操作后添加以下行:

FileUtils.mv 'modified.csv', 'original.csv', :force => true

答案 1 :(得分:1)

我找到了解决这个问题的简单方法。 FasterCSV库工作得很好。我确信在创建帖子到现在之间约7年可能与它有关,但我认为值得注意。

在我看来,在阅读CSV文件时,FasterCSV :header_converters选项没有详细记录。但是,不是分配符号(header_converters: :symbol),而是可以分配lambda(header_converters: lambda {...})。当CSV库读取文件时,它使用lambda转换标题。然后,可以保存反映已转换标头的新CSV文件。

例如:

options = {
  headers: true,
  header_converters: lambda { |h| HEADER_MAP.keys.include?(h.to_sym) ? HEADER_MAP[h.to_sym] : h }
}

table = CSV.read(FILE_TO_PROCESS, options)

File.open(PROCESSED_FILE, "w") do |file|
  file.write(table.to_csv)
end

答案 2 :(得分:0)

重写CSV文件标题是将导出的CSV文件转换为导入的任何人的常见要求。

我发现以下方法给了我所需要的东西:

lookup_headers = { "old": "new", "cat": "dog" } # The desired header swaps

CSV($>, headers: true, write_headers: true) do |csv_out|
  CSV.foreach( ARGV[0],
               headers: true, 
               # the following lambda replaces the header if it is found, leaving it if not...
               header_converters: lambda{ |h| lookup_headers[h] || h}, 
               return_headers: true) do |master_row|

    if master_row.header_row?
      # The headers are now correctly replaced by calling the updated headers
      csv_out << master_row.headers
    else
      csv_out << master_row
    end
  end
end

希望这有帮助!