【问题标题】:Parse CSV Data with Ruby使用 Ruby 解析 CSV 数据
【发布时间】:2013-08-24 11:32:32
【问题描述】:

我正在尝试根据两个条件返回特定的单元格值。

逻辑:

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

【问题讨论】:

    标签: ruby parsing csv


    【解决方案1】:

    你们确实很亲近。您唯一的错误是将 search_criteria 哈希值设置为字符串 '1' 而不是数字。既然你有converters: :numeric 在那里find_all 正在比较1'1' 并得到false。你可以改变它,你就完成了。

    或者,这应该适合你。

    关键是线

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

    Hash[row] 将行转换为哈希而不是数组。 Select 生成一个新的散列,其中仅包含出现在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'] }
    

    【讨论】:

      【解决方案2】:

      可能……

      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-03-25
        • 2013-12-11
        相关资源
        最近更新 更多