【问题标题】:Change Headers for Certain Columns in CSV File更改 CSV 文件中某些列的标题
【发布时间】:2018-10-13 23:39:21
【问题描述】:

我有一个 CSV 文件,我只想更改某些列的标题(我的实际文件中大约有 20 个)。这是一个示例 CSV 文件:

CSV 文件

"name","blah_01_blah","foo_1_01_foo","bacon_01_bacon","bacon_02_bacon"
"John","yucky","summer","yum","food"
"Mary","","","cool","sundae"

我一直在尝试使用 File/IO 类,但是当它读取文件以执行 gsub 时,它会删除每个字符串周围用逗号分隔的所有引号。这是我正在使用的代码:

Ruby 代码

file = 'file.csv'

replacements = {
    'blah_01_blah' => 'newblah1',
    'foo_01_foo' => 'coolfoo1',
    'bacon_01_bacon' => 'goodpig1',
    'bacon_01_bacon' => 'goodpig2'
}

matcher = /#{replacements.keys.join('|')}/

outdata = File.read(file).gsub(matcher, replacements)

File.open(file, 'w') do |out|
out << outdata
end

我最终得到的是 CSV 文件中的这个:

新建 CSV 文件

name,blah_01_blah,foo_1_01_foo,bacon_01_bacon,bacon_02_bacon
John,yucky,summer,yum,food
Mary,"","",cool,sundae

它将引号保留在空白字段中,但将它们从其他地方的字符串中取出。我想保留这些引号,以防由于某种原因流氓逗号最终出现在某个字符串中,这样它就不会被丢弃。如何更改标题而不丢失字符串周围的引号?

编辑 - 这是我希望文件最后的样子。

预期结果 CSV 文件

"name","newblah1","coolfoo1","goodpig1","goodpig2"
"John","yucky","summer","yum","food"
"Mary","","","cool","sundae"

谢谢!

【问题讨论】:

  • 当您只想编辑 标题(第一行)时,为什么还要阅读 整个文件 (File.read(file))?这是非常低效的,并且可能容易出错。
  • 想要简历最后是什么样子?

标签: ruby csv


【解决方案1】:

您根本不需要处理 CSV:

File.write(
  file,
  File.readlines(file).tap do |lines|
    lines.first.gsub!(matcher, replacements)
  end.join
)

File#readlines.

这里的诀窍是我们实际上只处理第一行,就像处理纯文本一样。

【讨论】:

  • 好的,越来越近了。您的回答可以更改标题,但现在由于某种原因,我在每个现有行之间添加了一个空白行。
【解决方案2】:

让我们首先创建输入 CSV 文件。

text =<<_
"name","blah_01_blah","foo_1_01_foo","bacon_01_bacon","bacon_02_bacon"
"John","yucky","summer","yum","food"
"Mary","","","cool","sundae"
_

file_in  = 'file_in.csv'
file_out = 'file_out.csv'
File.write(file_in, text)
  #=> 137

这里是replacements 哈希,我稍微简化了一下。

replacements = {'blah_01_blah'=>'newblah1', 'foo_01_foo'=>'coolfoo1',
                'bacon_01_bacon'=>'goodpig1'}

第一个任务是修改这个哈希,如果它没有键kreplacements[k] 将返回k。为此,我们使用方法Hash#default_proc=

replacements.default_proc = ->(_,k) { k }

以下是如何使用此哈希的两个示例。

replacements['bacon_01_bacon']
  #=> "goodpig1"
replacements['name']
  #=> "name"`

后面紧随其后,因为replacements 没有密钥'name'

代码如下。

require 'csv'

f_in = CSV.read(file_in, headers:true)
CSV.open(file_out, 'w') do |csv_out|
  csv_out << replacements.values_at(*f_in.headers)
  f_in.each { |row| csv_out << row }
end
  #=> #<CSV::Table mode:col_or_row row_count:3>

注意

f_in.headers
  #=> ["name", "blah_01_blah", "foo_1_01_foo", "bacon_01_bacon", "bacon_02_bacon"]

让我们看看输出文件。

puts File.read(file_out)

打印

name,newblah1,foo_1_01_foo,goodpig1,bacon_02_bacon
John,yucky,summer,yum,food
Mary,"","",cool,sundae

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-12
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    • 2013-03-14
    • 2020-07-15
    • 2021-05-02
    • 2014-03-26
    相关资源
    最近更新 更多