【发布时间】:2015-08-10 08:23:55
【问题描述】:
我尝试使用 ruby csv lib 解析 csv 文件,但该文件有两列具有相同的标题文本。是否可以访问列 :column 即 row[:column_1] 和 row[:column_2] 或 row[:column][0] 和 row[:column][1] 还是应该使用索引来访问它?
谢谢
【问题讨论】:
我尝试使用 ruby csv lib 解析 csv 文件,但该文件有两列具有相同的标题文本。是否可以访问列 :column 即 row[:column_1] 和 row[:column_2] 或 row[:column][0] 和 row[:column][1] 还是应该使用索引来访问它?
谢谢
【问题讨论】:
如果您有重复的标题,那么 row[:column] 将返回第一个值。
您必须使用索引进行迭代。
require 'csv'
filename = "/path/to/csv"
csv = CSV.table(filename, {:headers => :first_row})
headers = csv.headers
csv.each_with_index do |row, i|
(0...headers.length).each do |j|
column_header = headers[j]
column_value = row[j]
puts " Row #{i}: Header '#{column_header}' has value '#{column_value}'"
end
end
【讨论】:
你可以使用索引:
require 'csv'
data = <<data
a,b,c,b
1,2,3,4
9,8,7,6
data
csv = CSV.new(data, :col_sep => ',', :headers => true)
csv.each do |row|
puts "b: %s, 1: %s, 3: %s" % [row['b'],row[1], row[3]]
end
注意,数字从0开始。
您还可以使用其他方法扩展行对象:
require 'csv'
class CSV::Row
def b_1; self[1]; end
def b_2; self[3]; end
end
data = <<data
a,b,c,b
1,2,3,4
9,8,7,6
data
csv = CSV.new(data, :col_sep => ',', :headers => true)
csv.each do |row|
puts row.b_1
puts row.b_2
end
此逻辑将定义方法 b_1 和 b_2 用于所有行对象(也用于完全不同的 CSV 文件)。所以这可能是一个小脚本的解决方案,但我不会在更大的项目中使用它。
您也可以在每个循环中临时定义该方法:
require 'csv'
data = <<data
a,b,c,b
1,2,3,4
9,8,7,6
data
csv = CSV.new(data, :col_sep => ',', :headers => true)
csv.each do |row|
class << row
def b_1; self[1]; end
def b_2; self[3]; end
end
puts row.b_1
puts row.b_2
end
如果您有多个循环,您还可以定义一个模块并扩展每一行:
require 'csv'
module RowExtension
def b_1; self[1]; end
def b_2; self[3]; end
end
data = <<data
a,b,c,b
1,2,3,4
9,8,7,6
data
csv = CSV.new(data, :col_sep => ',', :headers => true)
csv.each do |row|
row.extend RowExtension
puts row.b_1
puts row.b_2
end
也许还可以扩展 CSV 类以返回特定的行元素。但这超出了我的实际知识范围。
另一个解决方案是使用 headers-option。 headers-options 定义了标题字段,因此您可以定义自己的标题:
require 'csv'
data = <<data
a,b,c,b
1,2,3,4
9,8,7,6
data
csv = CSV.new(data, :col_sep => ',', :headers => %w{a b_1 c b_2})
csv.each do |row|
puts row['b_1']
puts row['b_2']
end
现在您必须忽略第一行(旧标题行)。
【讨论】:
我不确定你的问题。但是如果您想以表格格式访问您的 CSV 数据,只需使用 CSV::Table 类,如下所示
csv = CSV.table(filename)
Here 是关于方法的更多信息
如果你想在解析数据后以列为单位访问你的数据,只需将数组转置如下
csv = CSV.parse('csv_string')
csv_array = csv.transpose
【讨论】: