在Rails中解析制表符分隔的文件

12
我有一个长这样的文件。
ID Name  Car
1  Mike  Honda
2  Adam  Jim

这些值是以制表符分隔的,我想用Ruby解析它并将其放入我的数据库中。我尝试了以下方法:
require 'csv'

CSV.foreach("public/files/example.tab", {:col_sep => "\t"}) do |row|
  @stuff = row[0]
end

但是@stuff仅返回整个对象,并没有使用我指定的列分隔符。

它也没有考虑到第一行是标题。

我该如何在Ruby中解析制表符分隔的文件,以及如何告诉它第一行是标题?


谢谢,巧合的是:col_sep => "\t" 今天救了我一命 :D - Romans 8.38-39
3个回答

4

我在使用FasterCSV和Ruby 1.8.7时取得了成功,我相信它现在是1.9核心csv库,使用方法如下:

table = FasterCSV.read(result_file.to_file.path, { :headers => true, :col_sep => "\t", :skip_blanks => true })
unless table.empty?
    header_arry = Array.new
    table.headers.each do |h|
      #your header logic, e.g.
      # if h.downcase.include? 'pos'
        # header_arry << 'position'
      # end
      # simplest case here
      header_arry << h.downcase
      #which produces an array of column names called header_arry
    end

    rows = table.to_a
    rows.delete_at(0)
    rows.each do |row|
      #convert to hash using the column names
      hash = Hash[header_arry.zip(row)]
      # do something with the row hash
    end
  end

“undefined local variable or method `header_arry'” - 我不认为文本文件以任何特殊方式定义了标题...抱歉,我很新手rails。 - Mike Silvis
我在头部区域添加了更多的解释。据我所知,它只使用第一行,不需要定义为标题。 - user1047725

2

更新

请查看宝石“smarter_csv”https://github.com/tilo/smarter_csv/,它具有从CSV数据创建哈希的几个有趣功能。

以前的回答

以下是我的做法(在此过程中,我将由CSV.read或CSV.parse返回的“数组套数组”转换为“哈希数组”……这使得数据看起来更像ActiveRecord数据,并且稍后以这种方式处理更容易)。

require 'csv'

def process(csv_array)  # makes arrays of hashes out of CSV's arrays of arrays
  result = []
  return result if csv_array.nil? || csv_array.empty?
  headerA = csv_array.shift             # remove first array with headers from array returned by CSV
  headerA.map!{|x| x.downcase.to_sym }  # make symbols out of the CSV headers
  csv_array.each do |row|               #    convert each data row into a hash, given the CSV headers
    result << Hash[ headerA.zip(row) ]  #    you could use HashWithIndifferentAccess here instead of Hash
  end
  return result
end

# reading in the CSV data is now just one line:

csv_data = process( CSV.read( filename , { :col_sep => "\t"}) )

 => [{:id=>"1", :name=>"Mike", :car=>"Honda"}, 
     {:id=>"2", :name=>"Adam", :car=>"Jim"}] 

现在,您可以像这样处理数据:
csv_data.each do |hash|
  # ...
end

另请参阅:

http://as.rubyonrails.org/classes/HashWithIndifferentAccess.html

http://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html


看看宝石'smarter_csv' - 它有一些有趣的选项! - Tilo

0
我使用了简单的方法来解析CSV数据。在这里,分隔符可以是制表符、空格、逗号或分号。它会返回一个字段数组。
row_data = File.new("your_file.csv").read

row_data = row_data.split(/[ ,;\s]/).reject(&:empty?)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接