2013-08-21 2 views
2

Я пытаюсь вернуть значение конкретной ячейки на основе двух критериев.Parse CSV Data with Ruby

Логика:

If ClientID = 1 and BranchID = 1, puts SurveyID

Использование Руби 1.9.3, я хочу, чтобы в основном смотреть через файл первенствовать и для двух конкретных значений, расположенных в столбце ClientID и BranchID, возвращает соответствующее значение в 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