2013-08-21 99 views
2

我想根据两个条件返回一个特定的单元格值。用Ruby解析CSV数据

逻辑:

If ClientID = 1 and BranchID = 1, puts SurveyID

使用Ruby 1.9.3,我想基本上是通过一个excel文件和位于ClientIDBranchID柱内的两个具体数值看,在返回相应的值SurveyID栏。

这是我到目前为止,我在我的在线搜索中找到的。它似乎有希望的,但没有运气:

require 'csv' 

# Load file 
csv_fname = 'FS_Email_Test.csv' 

# Key is the column to check, value is what to match 
search_criteria = { 'ClientID' => '1', 
        'BranchID' => '1' } 

options = { :headers  => :first_row, 
      :converters => [ :numeric ] } 

# Save `matches` and a copy of the `headers` 
matches = nil 
headers = nil 

# Iterate through the `csv` file and locate where 
# data matches the options. 

CSV.open(csv_fname, "r", options) do |csv| 
    matches = csv.find_all do |row| 
    match = true 
    search_criteria.keys.each do |key| 
     match = match && (row[key] == search_criteria[key]) 
    end 
    match 
    end 
    headers = csv.headers 
end 

# Once matches are found, we print the results 
# for a specific row. The row `row[8]` is 
# tied specifically to a notes field. 

matches.each do |row| 
    row = row[1] 
    puts row 
end 

我知道代码的最后位以下matches.each do |row|是无效的,但我离开它,希望它会是有意义的其他人。

我该怎么写puts surveyID if ClientID == 1 & BranchID == 1

回答

3

你非常接近确实如此。您唯一的错误是将search_criteria散列值设置为字符串'1'而不是数字。由于您有converters: :numeric那里find_all比较1'1'并得到false。你可以改变这一点,你就完成了。

此外,这应该为你工作。

的关键是线

Hash[row].select { |k,v| search_criteria[k] } == search_criteria 

Hash[row]行转换为哈希代替数组的数组。选择将生成一个新的散列,其中只有出现在search_criteria中的那些元素。然后,比较两个哈希值,看看它们是否相同。

require 'csv' 

# Load file 
csv_fname = 'FS_Email_Test.csv' 

# Key is the column to check, value is what to match 
search_criteria = { 
    'ClientID' => 1, 
    'BranchID' => 1, 
} 

options = { 
    headers: :first_row, 
    converters: :numeric, 
} 

# Save `matches` and a copy of the `headers` 
matches = nil 
headers = nil 

# Iterate through the `csv` file and locate where 
# data matches the options. 

CSV.open(csv_fname, 'r', options) do |csv| 
    matches = csv.find_all do |row| 
    Hash[row].select { |k,v| search_criteria[k] } == search_criteria 
    end 
    headers = csv.headers 
end 

p headers 


# Once matches are found, we print the results 
# for a specific row. The row `row[8]` is 
# tied specifically to a notes field. 

matches.each { |row| puts row['surveyID'] } 
+0

这工作完美。谢谢您的帮助! – Luigi

0

可能...

require 'csv' 

b_headers = false 
client_id_col = 0 
branch_id_col = 0 
survey_id_col = 0 

CSV.open('FS_Email_Test.csv') do |file| 
    file.find_all do |row| 
    if b_headers == false then 

     client_id_col = row.index("ClientID") 
     branch_id_col = row.index("BranchID") 
     survey_id_col = row.index("SurveyID") 
     b_headers = true 

     if branch_id_col.nil? || client_id_col.nil? || survey_id_col.nil? then 
     puts "Invalid csv file - Missing one of these columns (or no headers):\nClientID\nBranchID\nSurveyID" 
     break 
     end 

    else 
     puts row[survey_id_col] if row[branch_id_col] == "1" && row[client_id_col] == "1" 
    end 

    end 
end