我需要将标题和数据写入csv。我面临的问题是我的数据可能会改变顺序。我想在paricular标题列下准确映射我的数据。谁能告诉我怎么做?
Ex:我的数据看起来像是
Min6 ItemNumber FC1 FC2 Retailer Brand Description Size
630 12549 0 0 Too-Tart SWEET&SOUR .7OZ
0 0 Ahold Too-Tart SWEET&SOUR .7OZ
0 0 Test Too-Tart SWEET&SOUR .7OZ
630 12550 0 0 Too SWEET&Salt .60Z
0 0 Test Too SWEET&SOUR .7OZ
0 0 Ahold Too SWEET&SOUR .23Z
我期待
Min6 ItemNumber FC1 FC2 Retailer Brand Description Size Ahold-Description Ahold-Brand Test-Description Test-Brand
630 12549 0 0 Too-Tart SWEET&SOUR .7OZ SWEET&SOUR Too-Tart SWEET&SOUR Too-Tart
630 12549 0 0 Too-Tart SWEET&Salt .6OZ SWEET&SOUR Too SWEET&SOUR Too
零售商的订单可能会发生变化,许多零售商都会在那里。对于每个新零售商,将创建新的标题。如果重复零售商,那么我想将他的品牌和描述映射到已经创建的标题下。
class CouponsDataPreProcessor < Transformer
def run(path)
@records = []
input_base_name = File.basename(path, '.csv')
first_row = true
output_file = File.join('public', "coupons_data_preprocessor_#{input_base_name}_#{Time.now.strftime('%Y%m%d%H%M')}.csv")
CSV.open(output_file, 'w') do |csv|
CSV.foreach(path, {:headers => true}) do |row|
if first_row
@headers = row.headers
first_row = false
end
if row['ItemNumber'].present?
@records << row.fields
else
form_retailer_headers_and_fields(row)
end
end
csv << @headers
@records.each { |record| csv << record }
end
output_file
end
def form_retailer_headers_and_fields(row)
retailer = row['Retailer']
unless @headers.include?("Description-#{retailer}")
@headers.push("Description-#{retailer}", "Brand-#{retailer}", "SubBrand-#{retailer}", "Size-#{retailer}")
end
@records.last.push(row['Description'], row['Brand'], row['SubBrand'], row['Size'])
end
def self.about
'Preprocess coupons data into input line items'
end
end
如果零售商重复并且他的顺序不同,那么我无法将他的价值完全映射到他的标题栏下(例如:品牌零售商名称)
如何使用key作为标头和值创建一个行对象作为该标头的值并将其推入输出csv文件?
答案 0 :(得分:1)
您的代码中似乎存在多个错误。
(第1行)您继承自Transformer
,但您似乎无法重复使用Transformer中的任何方法。考虑删除继承。
(第1行)您需要require 'csv'
(第4行)也许你打算写File.basename(path << '.csv')
(第14行)您编写了if row['ItemNumber'].present?
但如果该列为空,则行[&#39; ItemNumber&#39;]将为nil,因此程序将中止MethodMissing。 您可能打算在activesupport gem中使用present?
方法,Stack Overflow用户需要测试这部分代码
我不认为CSV库有一个工具来检测前两列(例如第3行)是空白的,所以我认为你需要使用另一个工具来预处理,该工具在使用CSV之前标识列
您可以编写一种方法来识别列号,但我只是笨拙且手动完成(请使用更整洁的代码编辑我的答案):
COMMA = ','
f = File.open(path)
g = File.open('commas.csv', mode='w')
lines = f.readlines
lines = lines.reject{|ln| ln.length < 61} # reject the short line(s)
lines_with_commas = lines.collect{|ln| ln[0..3] << COMMA << ln[4..17] \
<< COMMA << ln[18..23] << COMMA << ln[24..27] << COMMA << ln[28..38] \
<< COMMA << ln[39..47]<< COMMA << ln[48..60]<< COMMA << ln[61..-1]}
lines_with_commas.each{ |ln| g.write(ln)}
g.close
然后,您可以一次性导入CSV并搜索零售商。
> table = CSV.table('commas.csv')
> table[:retailer_].collect(&:strip).uniq
=> ["", "Ahold", "Test"]