2014-09-23 96 views
0

我的目標是將一列CSV文件導入到Ruby數組中。這是一個自包含的Ruby腳本,而不是應用程序。我將在終端中運行腳本並獲取輸出。如何將CSV文件的列導入到Ruby數組中?

我無法找到導入文件的最佳方式,並找到將文件名稱動態插入該代碼行的最佳方法。文件名每次都會有所不同,並且會被用戶傳入。我正在使用$stdin.gets.chomp向用戶詢問文件名,並將其設置爲file_name

有人可以幫助我嗎?這是我對腳本的這部分有什麼:

require 'csv' 
    zip_array = CSV.read("path/to/file_name.csv") 

我需要能夠在上面插入適當的文件路徑。它是否正確?我怎麼在那裏得到那個路徑名?也許我需要完全重新構建我的腳本,但有關如何執行此操作的任何建議?

+0

要求輸入的程序通常是非常煩人的。爲什麼不讓文件名成爲命令行參數?這些都可以在'ARGV'中找到。 – tadman 2014-09-23 19:01:54

+0

如果該文件(無關緊要)將成爲程序文件夾中唯一的csv文件,則可以使用Dir.glob(「*。csv」)[0]。這樣你就不必擔心這個名字會一直在改變。 – daremkd 2014-09-23 19:19:07

回答

1

首先,你需要從$stdin.gets.chomp指派返回值給一個變量:

foo = $stdin.gets.chomp 

這將輸入的輸入端分配到foo

你並不需要使用$stdin不過,因爲gets將默認使用標準輸入通道:

foo = gets.chomp 

在這一點上使用變量作爲read參數:

zip_array = CSV.read(foo) 

這些都是基本的編碼,並涵蓋在任何語言的介紹書中。

2

我想這裏有兩個問題。首先是從命令行獲取用戶輸入。通常的做法是使用ARGV。在您的程序中,您可以執行file_name = ARGV[0],以便用戶可以在命令行上輸入ruby your_program.rb path/to/file_name.csv

接下來是關於閱讀CSV。使用CSV.read將採用整個CSV,而不僅僅是一個列。如果你想選擇很多的一列,你可能會更好做:

zip_array = [] 
CSV.foreach(file_name) { |row| zip_array << row[whichever_column] } 
1

好了,第一個問題:

一個)的文件名會在每次運行不同的(我假定這將永遠是一個CSV文件,對吧?)

你可以通過創建一個文件夾,說你的Ruby腳本中的input_data解決這個問題。然後執行:

Dir.glob('input_data/*.csv') 

這將生成一個以CSV結尾的文件夾內的所有文件的數組。如果我們假設會出現在該文件夾的時間(使用不同的名稱)只有1個文件,我們可以這樣做:

file_name = Dir.glob('input_data/*.csv')[0] 

這樣你會動態獲取的文件路徑,無論該文件是什麼命名。如果CSV文件是相同的目錄中的Ruby腳本中,你可以這樣做:

Dir.glob('*.csv')[0] 

現在,進口只有1列到一個Ruby陣列(讓我們假設它是第一列):

require 'csv' 
array = [] 
CSV.foreach(file_name) do |csv_row| 
    array << csv_row[0] # [0] for the first column, [1] for the second etc. 
end 

如果您的CSV文件包含標頭,該怎麼辦?假設你的列名是'Total'。你可以這樣做:

require 'csv' 
array = [] 
CSV.foreach(file_name, headers: true) do |csv_row| 
    array << csv_row['Total'] 
end 

現在,如果你的列是第一列不要緊,第三等,只要它有一個名爲「總計」欄頭,紅寶石會發現它。

CSV.foreach逐行讀取文件,適用於大文件。 CSV.read將立即讀取,但使用它可以使您的代碼更加簡潔:

array = CSV.read(, headers: true).map do |csv_row| 
    csv_row['Total'] 
end 

希望這對我有所幫助。