如何使用Ruby映射和编辑CSV文件

如何使用Ruby映射和编辑CSV文件,ruby,csv,Ruby,Csv,有没有一种方法可以在Ruby中使用map方法编辑CSV文件?我知道我可以使用以下方法打开文件: CSV.open("file.csv", "a+") 并添加内容,但我必须编辑一些特定的行 foreach方法仅在读取文件时有用(如果我错了,请纠正我) 我检查了红宝石,但找不到任何有用的信息 我的CSV文件少于1500行,因此我不介意读取所有行。以下是我编写的一个小脚本,作为一个示例,介绍如何读取CSV数据、对数据执行某些操作,然后将编辑的文本写入新文件: 读写csv.rb: #!/usr/bin

有没有一种方法可以在Ruby中使用
map
方法编辑CSV文件?我知道我可以使用以下方法打开文件:

CSV.open("file.csv", "a+")
并添加内容,但我必须编辑一些特定的行

foreach
方法仅在读取文件时有用(如果我错了,请纠正我)

我检查了红宝石,但找不到任何有用的信息


我的CSV文件少于1500行,因此我不介意读取所有行。

以下是我编写的一个小脚本,作为一个示例,介绍如何读取CSV数据、对数据执行某些操作,然后将编辑的文本写入新文件:

读写csv.rb:

#!/usr/bin/env ruby
require 'csv'

src_dir = "/home/user/Desktop/csvfile/FL_insurance_sample.csv"
dst_dir = "/home/user/Desktop/csvfile/FL_insurance_sample_out.csv"
puts " Reading data from  : #{src_dir}"
puts " Writing data to    : #{dst_dir}"
#create a new file 
csv_out = File.open(dst_dir, 'wb')
#read from existing file
CSV.foreach(src_dir , :headers => false) do |row|

  #then you can do this 
  # newrow = row.each_with_index { |rowcontent , row_num| puts "#     {rowcontent} #{row_num}" }

  # OR array to hash .. just saying .. maybe hash of arrays.. 
  #h = Hash[*row]
  #csv_out << h

  # OR use map  
  #newrow = row.map(&:capitalize)
  #csv_out << h

  #OR use each  ... Add and end 
  #newrow.each do |k,v| puts "#{k} is #{v}"

  #Lastly,  write back the edited , regexed data ..etc to an out file.
  #csv_out << newrow

end

# close the file 
csv_out.close
输入文件数据如下所示:

policyID,statecode,county,eq_site_limit,hu_site_limit,fl_site_limit,fr_site_limit,tiv_2011,tiv_2012,eq_site_deductible,hu_site_deductible,fl_site_deductible,fr_site_deductible,point_latitude,point_longitude,line,construction,point_granularity
119736,FL,CLAY COUNTY,498960,498960,498960,498960,498960,792148.9,0,9979.2,0,0,30.102261,-81.711777,Residential,Masonry,1
448094,FL,CLAY COUNTY,1322376.3,1322376.3,1322376.3,1322376.3,1322376.3,1438163.57,0,0,0,0,30.063936,-81.707664,Residential,Masonry,3
206893,FL,CLAY COUNTY,190724.4,190724.4,190724.4,190724.4,190724.4,192476.78,0,0,0,0,30.089579,-81.700455,Residential,Wood,1
333743,FL,CLAY COUNTY,0,79520.76,0,0,79520.76,86854.48,0,0,0,0,30.063236,-81.707703,Residential,Wood,3
172534,FL,CLAY COUNTY,0,254281.5,0,254281.5,254281.5,246144.49,0,0,0,0,30.060614,-81.702675,Residential,Wood,1
有没有办法在Ruby中使用map方法编辑CSV文件

是的:


desired_index=[3,4,5]#这些是您要修改的行
编辑的_行=行_数组。每个_带有_index.map do |行,索引|
如果需要,索引。包括?(索引)
#只需返回该行即可
#或者在这里修改
行[3]=“湿婆”
#在每个编辑的行中存储索引以跟踪行
[索引,第行]
结束
紧凑型
#使用更新的数据更新主行数组
已编辑的_行。每个{|行|行_数组[行[0]]=行[1]}
#现在更新文件

CSV.open('sample2.CSV','wb'){| CSV | rows|u数组。每个{| row | CSV使用
each.with_index()
另一个答案:

rows\u array=CSV.read('sample.CSV'))
所需的_索引=[3,4,5]。排序#这些是您要修改的行
行数组。每个。具有_索引(所需的_索引[0])do |行,索引|
如果需要,索引。包括?(索引)
#在这里修改
行\数组[索引][目标\列]=“修改”
结束
结束
#现在更新文件

open('sample3.CSV','wb'){| CSV | rows|u数组。可以使用"
'a+'
,更好的问题是您是否应该这样做?如果您的代码在运行中期崩溃,则很有可能损坏您唯一的文件,这在生产环境中是不可接受的。相反,请使用
foreach
读取原始文件并开始写入全新的文件,在适当的位置添加更改。之后新文件已完全写入,请将旧文件重命名为备份文件,将新文件重命名为旧文件的名称,然后您可以自由删除旧文件。不要将原始文件弄脏,因为它速度较慢且不可扩展。以下任一项是否回答了您的问题@BadooPlease read“”。我们想知道您试图解决的问题,以及为什么它不起作用。如果没有这些问题,您似乎没有尝试并希望我们为您编写代码,这不是正确的方式。请参阅,您没有说明如何确定必须更改哪些行。按行号?按行中的内容?通常,不,
map
不是一个好的选择它意味着每一行都必须通过该块。相反,一个简单的条件测试在这些行上迭代并寻找需要更改的行会更明智。这是在对数据进行SLURP,这不是一个可伸缩的解决方案,所以只有在保证文件永远不会超过可用内存的情况下才这样做。请参阅。小心使用g这项技术可以将整个文件存储在内存中。除非保证输入永远不会超过内存,否则逐行解决方案会更安全、更快。请参阅感谢@Tin Man对这项技术的修改。Tin Man就是这个人。您应该使用
file.open(dst_dir,'wb'的块形式)
而不是赋值给变量。这是Ruby方式。我认为有一个错误:
csv_out=File.open(dst_dir,'wb')
应该是
csv_out=csv.open(dst_dir,'wb')
,否则写入的内容将是对应于不同元素串联的单行。
policyID,statecode,county,eq_site_limit,hu_site_limit,fl_site_limit,fr_site_limit,tiv_2011,tiv_2012,eq_site_deductible,hu_site_deductible,fl_site_deductible,fr_site_deductible,point_latitude,point_longitude,line,construction,point_granularity
119736,FL,CLAY COUNTY,498960,498960,498960,498960,498960,792148.9,0,9979.2,0,0,30.102261,-81.711777,Residential,Masonry,1
448094,FL,CLAY COUNTY,1322376.3,1322376.3,1322376.3,1322376.3,1322376.3,1438163.57,0,0,0,0,30.063936,-81.707664,Residential,Masonry,3
206893,FL,CLAY COUNTY,190724.4,190724.4,190724.4,190724.4,190724.4,192476.78,0,0,0,0,30.089579,-81.700455,Residential,Wood,1
333743,FL,CLAY COUNTY,0,79520.76,0,0,79520.76,86854.48,0,0,0,0,30.063236,-81.707703,Residential,Wood,3
172534,FL,CLAY COUNTY,0,254281.5,0,254281.5,254281.5,246144.49,0,0,0,0,30.060614,-81.702675,Residential,Wood,1
rows = CSV.open('sample.csv')
rows_array = rows.to_a
rows_array = CSV.read('sample.csv')
desired_indices = [3, 4, 5] # these are rows you would like to modify

edited_rows = rows_array.each_with_index.map do |row, index| 
  if desired_indices.include?(index)

    # simply return the row
    #   or modify over here
    row[3] = 'shiva'

    # store index in each edited rows to keep track of the rows
    [index, row]

  end
end.compact

# update the main row_array with updated data
edited_rows.each{|row| rows_array[row[0]] = row[1]}

# now update the file
CSV.open('sample2.csv', 'wb') { |csv| rows_array.each{|row| csv << row}}
rows_array = CSV.read('sample.csv')

desired_indices = [3, 4, 5].sort # these are rows you would like to modify
rows_array.each.with_index(desired_indices[0]) do |row, index| 
  if desired_indices.include?(index)

    # modify over here
    rows_array[index][target_column] = 'modification'

  end
end

# now update the file
CSV.open('sample3.csv', 'wb') { |csv| rows_array.each{|row| csv << row}}