2016-12-01 56 views
0

這裏是我的代碼:遇到問題把我頭回我的CSV文件

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

+0

請編輯您的帖子,包括你正在使用的數據的一個例子。 –

+0

@Jordan,請參閱編輯。 – Forwarding

+1

我很高興我的答案幫助解決了您的問題。最後一個與CSV無關的註釋:當您使用['File.open'](https://ruby-doc.org/core-2.3.1/File.html#method-c-open)時,您需要確保文件在您完成後關閉。最簡單的方法是使用塊形式,就像我的答案一樣,它會自動關閉文件。否則,你必須在由File.open返回的File對象上調用['close'](https://ruby-doc.org/core-2.3.1/IO.html#method-i-close)。您應該在'ensure'塊中執行此操作,以便即使出現錯誤也會發生。 –

回答

3

你的問題的根源是,你不使用由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