使用 FasterCSV 替换一个 CSV 列中的文本

发布于 2024-10-07 16:56:47 字数 761 浏览 3 评论 0原文

作为 Ruby 的新手,我试图弄清楚如何使用 FasterCSV 执行以下操作: 打开一个 CSV 文件,通过标题选择一列,在此列中仅将所有出现的字符串 x 替换为 y,将新文件写入 STDOUT。 以下代码几乎可以工作:

filename = ARGV[0]
csv = FCSV.read(filename, :headers => true, :header_converters => :symbol, :return_headers => true, :encoding => 'u') 
mycol = csv[:mycol]
# construct a mycol_new by iterating over mycol and doing some string replacement
puts csv[:mycol][0] # produces "MyCol" as expected
puts mycol_new[0] # produces "MyCol" as expected
csv[:mycol] = mycol_new
puts csv[:mycol][0] # produces "mycol" while "MyCol" is expected
csv.each do |r|
  puts r.to_csv(:force_quotes => true)
end

唯一的问题是存在我不期望的标头转换。如果所选列的标题在 csv 表中的列替换之前为“MyCol”,则替换后的标题为“mycol”(请参阅​​代码中的注释)。为什么会出现这种情况?以及如何避免呢?谢谢。

Being relatively new to Ruby, I am trying to figure out how to do the following using FasterCSV:
Open a CSV file, pick a column by its header, in this column only replace all occurrences of string x with y, write out the new file to STDOUT.
The following code almost works:

filename = ARGV[0]
csv = FCSV.read(filename, :headers => true, :header_converters => :symbol, :return_headers => true, :encoding => 'u') 
mycol = csv[:mycol]
# construct a mycol_new by iterating over mycol and doing some string replacement
puts csv[:mycol][0] # produces "MyCol" as expected
puts mycol_new[0] # produces "MyCol" as expected
csv[:mycol] = mycol_new
puts csv[:mycol][0] # produces "mycol" while "MyCol" is expected
csv.each do |r|
  puts r.to_csv(:force_quotes => true)
end

The only problem is that there is a header conversion where I do not expect it. If the header of the chosen column is "MyCol" before the substitution of the columns in the csv table it is "mycol" afterwards (see comments in the code). Why does this happen? And how to avoid it? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

半城柳色半声笛 2024-10-14 16:56:47

您可以在初始化行中更改一些有帮助的内容。更改

csv = FCSV.read(filename, :headers => true, :return_headers => true, :encoding => 'u') 

为:

csv = FCSV.read(filename, :headers => true, :encoding => 'u') 

我正在使用 CSV,它是 FasterCSV,只是它是 Ruby 1.9 的一部分。这将在当前目录中创建一个名为“temp.csv”的 CSV 文件,并修改“FName”字段:

require 'csv'

data = "ID,FName,LName\n1,mickey,mouse\n2,minnie,mouse\n3,donald,duck\n"

# read and parse the data
csv_in = CSV.new(data, :headers => true)

# open the temp file
CSV.open('./temp.csv', 'w') do |csv_out|

  # output the headers embedded in the object, then rewind to the start of the list
  csv_out << csv_in.first.headers
  csv_in.rewind

  # loop over the rows
  csv_in.each do |row|

    # munge the first name
    if (row['FName']['mi'])
      row['FName'] = row['FName'][1 .. -1] << '-' << row['FName'][0] << 'ay'
    end

    # output the record
    csv_out << row.fields
  end
end

输出如下所示:

ID,FName,LName
1,ickey-may,mouse
2,innie-may,mouse
3,donald,duck

There's a couple of things you can change in the initialization line that will help. Change:

csv = FCSV.read(filename, :headers => true, :return_headers => true, :encoding => 'u') 

to:

csv = FCSV.read(filename, :headers => true, :encoding => 'u') 

I'm using CSV, which is FasterCSV only it's part of Ruby 1.9. This will create a CSV file in the current directory called "temp.csv" with a modified 'FName' field:

require 'csv'

data = "ID,FName,LName\n1,mickey,mouse\n2,minnie,mouse\n3,donald,duck\n"

# read and parse the data
csv_in = CSV.new(data, :headers => true)

# open the temp file
CSV.open('./temp.csv', 'w') do |csv_out|

  # output the headers embedded in the object, then rewind to the start of the list
  csv_out << csv_in.first.headers
  csv_in.rewind

  # loop over the rows
  csv_in.each do |row|

    # munge the first name
    if (row['FName']['mi'])
      row['FName'] = row['FName'][1 .. -1] << '-' << row['FName'][0] << 'ay'
    end

    # output the record
    csv_out << row.fields
  end
end

The output looks like:

ID,FName,LName
1,ickey-may,mouse
2,innie-may,mouse
3,donald,duck
看春风乍起 2024-10-14 16:56:47

可以直接在 FasterCSV 对象中操作所需的列,而不是创建一个新列,然后尝试用新列替换旧列。

csv = FCSV.read(filename, :headers => true, :header_converters => :symbol, :return_headers => true, :encoding => 'u')
mycol = csv[:my_col]
mycol.each do |row|
  row.gsub!(/\s*;\s*/,"///") unless row.nil? # or any other substitution
csv.each do |r|
  puts r.to_csv(:force_quotes => true)
end

It is possible to manipulate the desired column directly in the FasterCSV object instead of creating a new column and then trying to replace the old one with the new one.

csv = FCSV.read(filename, :headers => true, :header_converters => :symbol, :return_headers => true, :encoding => 'u')
mycol = csv[:my_col]
mycol.each do |row|
  row.gsub!(/\s*;\s*/,"///") unless row.nil? # or any other substitution
csv.each do |r|
  puts r.to_csv(:force_quotes => true)
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文