【问题标题】:Having trouble putting my header back on my CSV file无法将我的标题放回我的 CSV 文件
【发布时间】:2017-04-16 16:57:30
【问题描述】:

这是我的代码:

require 'CSV'

contents = CSV.read('/Users/namename/Desktop/test.csv')
arr = []
first_row = contents[0]
contents.shift

contents.each do |row|
  if row[12].to_s =~ /PO Box/i or row[12].to_s =~ /^[[:digit:]]/
    #File.open('out.csv','a').puts('"'+row.join('","')+'"')
    arr << row
  else
    row[12], row[13] = row[13], row[12]
    #File.open('out.csv','a').puts('"'+row.join('","')+'"')
    arr << row
  end
end

arr.unshift(first_row)

arr.each do |row|
  File.open('out.csv', 'a').puts('"' + row.join('","') + '"')
end

首先我 .shift 以便我的标题字段不会捕获第一个 .each 循环的第一个条件中的模式(并最终交换)。然后我有条件地交换与模式匹配的单元格值,然后将正确移位的值存储在数组中。在此之后,我.unshift 尝试放回我存储在first_row 中的标题字段,但是当我查看生成的out.csv 文件时,我的所有标题都在中间。为什么?

示例数据:

https://gist.github.com/anonymous/e1017d3ba81634d9e1227e7fe49536cb

【问题讨论】:

  • 请编辑您的帖子以包含您正在使用的数据的示例。
  • @Jordan,请参阅编辑。
  • 很高兴我的回答帮助解决了您的问题。最后一点与 CSV 无关:当您使用 File.open 时,您需要确保文件在完成后关闭。最简单的方法是使用块形式,如我的回答,它将自动关闭文件。否则,您必须在File.open 返回的文件对象上调用close。您应该在 ensure 块中执行此操作,这样即使有错误也会发生。

标签: arrays ruby file csv


【解决方案1】:

问题的根源在于您没有使用 CSV 模块提供的功能。

首先,CSV.read 采用 :headers 选项,它会为您捕获标题,因此您不必担心它们,而且,作为奖励,您可以通过标题名称而不是数字索引访问字段(方便如果 CSV 字段的顺序发生变化)。使用:headers 选项,CSV.read 返回一个 CSV::Table 对象,我稍后将讨论它的另一个好处。

其次,您正在生成自己的人造 CSV 输出,而不是让 CSV 模块来完成。这尤其是不必要且危险的:

...puts('"' + row.join('","') + '"')

如果您的任何列值包含引号或换行符,需要转义,这将失败,非常糟糕。您可以改用CSV.generate_line(row),但如果您使用了上面的headers: 选项,则不需要这样做。就像我说的,它返回一个CSV::Table 对象,它有一个to_csv 方法,并且该方法接受一个:force_quotes 选项。这将像您想要的那样引用每个字段 - 更重要的是,安全。

有了以上知识,代码就变得更理智了:

require "csv"

contents = CSV.read('/Users/namename/Desktop/test.csv', headers: true)

contents.each do |row|
  next unless row["DetailActiveAddressLine1"] =~ /PO Box|^[[:digit:]]/i

  row["DetailActiveAddressLine1"], row["DetailActiveAddressLine2"] =
    row["DetailActiveAddressLine2"], row["DetailActiveAddressLine1"]
end

File.open('out.csv', 'a') do |file|
  file.write(contents.to_csv(force_quotes: true))
end

如果您愿意,可以在 Ideone 上查看正在运行的代码版本(当然,没有文件访问权限):http://ideone.com/IkdCpb

【讨论】:

    猜你喜欢
    • 2017-04-05
    • 1970-01-01
    • 1970-01-01
    • 2020-09-24
    • 1970-01-01
    • 2019-04-29
    • 2018-02-04
    • 2014-05-17
    相关资源
    最近更新 更多