4

我尝试使用 ruby​​ 标准 csv lib 将对象的 arr 转储到 csv.file ,称为 'a.csv'

http://ruby-doc.org/stdlib-1.9.3/libdoc/csv/rdoc/CSV.html#method-c-dump

dump(ary_of_objs, io = "", options = Hash.new)

但是在这种方法中,我如何转储到文件中?没有这样的例子存在和帮助。我谷歌它没有为我做的例子......

此外,文档说...

您可以提供的下一个方法是名为 csv_headers() 的实例方法。此方法预计将返回文档的第二行(再次作为数组),用于为每一列提供标题。默认情况下,如果字段标头以 @ 字符开头或调用 send() 将标头作为方法名称并将字段值作为参数传递,则 ::load 将设置一个实例变量。此方法仅在 Array 的第一个对象上调用。

任何人都知道如何将实例方法 csv_headers() 传递给这个转储函数?

4

2 回答 2

3

我还没有对此进行测试,但看起来 io 应该设置为一个文件。根据您链接的文档“io参数可用于序列化为文件”

就像是:
f = File.open("filename")
dump(ary_of_objs, io = f, options = Hash.new)

于 2012-06-01T05:16:03.827 回答
2

接受的答案并没有真正回答这个问题,所以我想我会举一个有用的例子。

首先,如果您查看http://ruby-doc.org/stdlib-1.9.3/libdoc/csv/rdoc/CSV.html上的文档,如果您将鼠标悬停在方法名称上,dump您会看到可以click to show source。如果你这样做,你会看到该dump方法尝试调用csv_headers你传入的第一个对象ary_of_objs

obj_template = ary_of_objs.first

...snip...

headers = obj_template.csv_headers

然后稍后您会看到该方法将调用csv_dump每个对象ary_of_objs并传入headers

ary_of_objs.each do |obj|
    begin
      csv << obj.csv_dump(headers)
    rescue NoMethodError
      csv << headers.map do |var|
        if var[0] == @
          obj.instance_variable_get(var)
        else
          obj[var[0..-2]]
        end
      end
    end
  end

所以我们需要增加每个条目array_of_objs来响应这两种方法。这是一个示例包装类,它将采用Hash, 并将哈希键作为 CSV 标头返回,然后能够根据标头转储每一行。

class CsvRowDump               
  def initialize(row_hash)     
    @row = row_hash            
  end                                                  

  def csv_headers              
    @row.keys                  
  end                          

  def csv_dump(headers)        
    headers.map { |h| @row[h] }
  end                          
end                       

不过还有一个问题。此dump方法希望在 CSV 文件顶部的标题之前写一个额外的行,如果由于顶部的代码而调用此方法,则无法跳过该行:

  # write meta information
  begin
    csv << obj_template.class.csv_meta
  rescue NoMethodError
    csv << [:class, obj_template.class]
  end     

即使你从CsvRowDump.csv_meta那里返回 '' 仍然是一个空行,解析需要标题。因此,让 letdump写下那行,然后在我们调用dump. 此示例假设您有一个哈希数组,它们都具有相同的键(这将是 CSV 标头)。

@rows = @hashes.map { |h| CsvRowDump.new(h) }
File.open(@filename, "wb") do |f|
  str = CSV::dump(@rows)
  f.write(str.split(/\n/)[1..-1].join("\n"))
end
于 2013-06-04T15:57:48.497 回答