2013-10-30 43 views
0

我有一個垂直的CSV文件看起來像這樣:如何從CSV中獲取特定的行值?

name,value 
case,"123Case0001" 
custodian,"Doe_John" 
PDate,"10/30/2013" 

我可以讀這樣的文件:

CSV.foreach("#{batch_File_Dir_cdata}", :quote_char => '"', :col_sep =>',', :row_sep =>:auto, :headers => true) do |record| 
ev_info = record[0] 
ev_val = record[1] 

的問題是,我需要一個特定的​​只是一個特定ev_info。我可以使用行號,但遠見告訴我這可能會改變。信息的名字也是一樣。我想查找具有特定信息名稱的行並獲取該值。

當我做foreach時,它獲取該值,然後越過它並留下一個空變量,因爲它繼續到其他行。

任何人都可以幫忙嗎?

+0

這不是一個CSV文件。 CSV不是「垂直」的,它們是「水平的」。有多少行構成一個記錄,只有四個? –

+0

它是一個csv,因爲有逗號分隔的值。這只是一個傳統的csv。 – missscripty

+0

除此之外應該沒有關係。如果csv有firstname,lastname並且我只想要第一個名字是「Steve」的行的姓氏值,那麼這可能嗎?這是同樣的問題。 – missscripty

回答

2

你有很多選擇,但最簡單的是分配給基於內容的變量,如:

ev_info = record[0] 
ev_val = record[1] if ev_info='special name' 

注意,雖然,你需要定義你是什麼變量分配給塊外部,否則將被創建爲本地變量,之後無法訪問。

或者,您可以讀取整個陣列,然後使用indexselect選擇您感興趣的記錄。

+0

謝謝你的迴應,但那沒有奏效。 CSV。foreach(「#{batch_File_Dir_cdata}」,::quote_char =>''',::col_sep =>','::row_sep =>:auto,:headers => true)do | record | ev_info = record [0] b_val = record [1] if ev_info ==「Batch」 end puts「#{b_val} is batch name」 我得到錯誤「NameError:undefined local variable or method'b_val'for main:Object」I don' t理解這將如何幫助,因爲它通過csv循環,csv的這一行在中間,所以當它完成foreach時,我不在第一列是我需要的那一行。除非我得到這個錯誤 – missscripty

+0

這種技術允許你從這一行中提取/保留你想要的任何信息,在我給出的例子中,它只提取/保留'record [1]',但是你可以提取/保留任何你想,包括整個記錄。至於你遇到的錯誤,你在我發佈的代碼的轉錄中有一個錯字。你有'b_val = ...',我有'ev_val = ...'。 –

+0

這不是一個錯字,我改變了它。我一貫。如果我保留它ev_val它仍然不起作用。 – missscripty

1

我會做這樣的:

require 'pp' 
require 'csv' 

ROWS_IN_RECORD = 4 

data = [] 
File.open('test.dat', 'r') do |fi| 
    loop do 
    record = {} 
    ROWS_IN_RECORD.times do 
     row = fi.readline.parse_csv 
     record[row.first] = row.last 
    end 
    data << record 
    break if fi.eof? 
    end 
end 

pp data 

運行輸出:

[{"name"=>"value", 
    "case"=>"123Case0001", 
    "custodian"=>"Doe_John", 
    "PDate"=>"10/30/2013"}, 
{"name"=>"value_2", 
    "case"=>"123Case0001 2", 
    "custodian"=>"Doe_John 2", 
    "PDate"=>"10/30/2013 2"}] 

它返回哈希的數組,所以每個散列是你通常從CSV得到記錄如果該文件是一個正常的CSV文件。

還有其他一些方法可以將輸入文件分解爲邏輯組,但這是可擴展的,只需稍作更改即可處理大量數據文件。對於一個巨大的文件只是在循環結束時處理每條記錄,而不是將它推到data變量上。

+0

但我只想要1個值。所以讓我們看看數據。它有你在第一個散列表中列出的內容。我只想抓住「Doe_John」的價值。所以我需要找到該行,第一列值是「保管人」。這有我需要的價值,即「Doe_John」。我怎麼說 - 只要給我名字是X的行的價值? – missscripty

+0

您正在使用的數據格式旨在將數據在電子表格或輕微按摩之間移動到數據庫。儘管可以通過讀取文件創建一個數組索引,但最好的解決方案是將其拉入數據庫,甚至像SQLite這樣的小數據庫。在上面的代碼中,如果你想訪問一個特定的記錄,你可以使用簡單的數組索引和哈希訪問:'data [0] ['custodian']'將返回「Doe_John」。但是,再次,這是一個糟糕的方式來處理這樣的文件。如果你的文件超出平凡的大小,我強烈建議查看數據庫。 –

+0

這只是與這個過程不同的方向。我們實際上吐出了這些csvs,並且需要將它們推送到腳本在文件夾中查找的過程中。它會檢查這些csv,併爲它們中的每一個讀取它們,使用特定行設置每個「批處理」的特徵,然後使用其餘信息爲批處理設置元數據值。我真的很想理解如何在我想要的行中搜索csv以獲取我想要的值,而不是嘗試重新創建過程。 – missscripty

1

我得到它的工作。我原來有以下幾點:

CSV.foreach("#{batch_File_Dir_cdata}", :quote_char => '"', :col_sep =>',', :row_sep =>:auto, :headers => true) do |record| 
    ev_info = record[0] 
    c_val = record[1] 
case when ev_info == "Custodian" 
cust = cval 
    end 
    end 
puts cust 

什麼,我需要做的是這樣的:

CSV.foreach("#{batch_File_Dir_cdata}", :quote_char => '"', :col_sep =>',', :row_sep =>:auto, :headers => true) do |record| 
    ev_info = record[0] 
    case when ev_info == "Custodian" 
    c_val = record[1] 
    end 
    end 

puts c_val