解析 CSV 文件中由分隔符分隔的每个文本的值
Parsing values of each and every text separated by delimiter in CSV file
正在尝试创建读取和显示 CSV 文件中每个值的方法。已将 CSV 文件的第一行指定为函数名称,可以调用这些函数来访问每个文本。
我还构建了一个对象数组,并将每个对象与 CSV 文件的行相关联。
CSV 文件的输入被视为由分隔符分隔的普通文本。假设-
name,age,city
Chris,43,Ohio
Tony,54,NYC
我的输出是正确的,它是通过提要生成器提取到另一个 CSV 文件的 class。
但我无法在命令行上解析此输出。我可以在 class 之外的 FeedGenerator 上直接调用方法,例如 -
FeedGenerator.name
FeedGenerator.age
FeedGenerator.city
目前我的代码根据此 class -
中提供的属性提供数据
class StarkFeedGenerator < FeedGenerator
def columns; %w(name); end
end
require 'csv'
class FeedGenerator
attr_accessor :source, :feed, :current_row
def initialize(source_name, feed_name)
@source = CSV.read(source_name, headers: true)
@current_row = Row.new
@feed = []
# define method by header of source file
@source.headers.each do |column|
@current_row.instance_eval do
define_singleton_method(column) do
self.row[column]
end
end
end
@feed = CSV.open(feed_name, 'wb+')
@feed << columns
end
def columns
%w(name age city)
end
def generate_feed
@source.each do |row|
@current_row.row = row
@feed << columns.map do |c|
@current_row.send(c)
end
end
end
def columns; raise 'unimplimented'; end
class Row
attr_accessor :row
# you can define unrecognized column mapping below
def name; name; end
def age; age; end
def city; city; end
end
end
class StarkFeedGenerator < FeedGenerator
def columns; %w(name); end
end
StarkFeedGenerator.new('Input.csv','new_feed.csv').generate_feed
预期结果:
FeedGenerator.name : Chris, tony
FeedGenerator.age : 43,54
FeedGenerator.city : Ohio, NYC
这是你想要的吗?
require 'csv'
class Feed
def initialize(source_name, column_names = [])
if column_names.empty?
column_names = CSV.open(source_name, 'r', &:first)
end
columns = column_names.reduce({}) { |columns, col_name| columns[col_name] = []; columns }
define_singleton_method(:columns) { column_names }
column_names.each do |col_name|
define_singleton_method(col_name.to_sym) { columns[col_name] }
end
CSV.foreach(source_name, headers: true) do |row|
column_names.each do |col_name|
columns[col_name] << row[col_name]
end
end
end
end
feed = Feed.new('input.csv')
puts feed.columns # ["name", "age", "city"]
puts feed.name # ["Chris", "Tony"]
puts feed.age # ["43", "54"]
puts feed.city # ["Ohio", "NYC"]
feed2 = Feed.new('input.csv', ['name'])
puts feed2.columns # ["name"]
puts feed2.name # ["Chris", "Tony"]
请注意,我刚刚创建了 Feed
class 而不是 FeedGenerator
,因为我认为创建一个生成器没有多大意义,而您只需 initialize
方法。
另请注意,如果您只想在调用 feed.name
时从 CSV 文件中读取数据,那么所有 CSV 行都将存储在内存中(如果您的 CSV 非常大则效果不佳),例如,这是另一种方法:
require 'csv'
class Feed
def initialize(source_name, column_names = [])
if column_names.empty?
column_names = CSV.open(source_name, 'r', &:first)
end
define_singleton_method(:columns) { column_names }
column_names.each do |col_name|
define_singleton_method(col_name.to_sym) do
columns = []
CSV.foreach(source_name, headers: true) do |row|
columns << row[col_name]
end
columns
end
end
end
end
feed = Feed.new('input.csv')
正在尝试创建读取和显示 CSV 文件中每个值的方法。已将 CSV 文件的第一行指定为函数名称,可以调用这些函数来访问每个文本。 我还构建了一个对象数组,并将每个对象与 CSV 文件的行相关联。 CSV 文件的输入被视为由分隔符分隔的普通文本。假设-
name,age,city
Chris,43,Ohio
Tony,54,NYC
我的输出是正确的,它是通过提要生成器提取到另一个 CSV 文件的 class。 但我无法在命令行上解析此输出。我可以在 class 之外的 FeedGenerator 上直接调用方法,例如 -
FeedGenerator.name
FeedGenerator.age
FeedGenerator.city
目前我的代码根据此 class -
中提供的属性提供数据 class StarkFeedGenerator < FeedGenerator
def columns; %w(name); end
end
require 'csv'
class FeedGenerator
attr_accessor :source, :feed, :current_row
def initialize(source_name, feed_name)
@source = CSV.read(source_name, headers: true)
@current_row = Row.new
@feed = []
# define method by header of source file
@source.headers.each do |column|
@current_row.instance_eval do
define_singleton_method(column) do
self.row[column]
end
end
end
@feed = CSV.open(feed_name, 'wb+')
@feed << columns
end
def columns
%w(name age city)
end
def generate_feed
@source.each do |row|
@current_row.row = row
@feed << columns.map do |c|
@current_row.send(c)
end
end
end
def columns; raise 'unimplimented'; end
class Row
attr_accessor :row
# you can define unrecognized column mapping below
def name; name; end
def age; age; end
def city; city; end
end
end
class StarkFeedGenerator < FeedGenerator
def columns; %w(name); end
end
StarkFeedGenerator.new('Input.csv','new_feed.csv').generate_feed
预期结果:
FeedGenerator.name : Chris, tony
FeedGenerator.age : 43,54
FeedGenerator.city : Ohio, NYC
这是你想要的吗?
require 'csv'
class Feed
def initialize(source_name, column_names = [])
if column_names.empty?
column_names = CSV.open(source_name, 'r', &:first)
end
columns = column_names.reduce({}) { |columns, col_name| columns[col_name] = []; columns }
define_singleton_method(:columns) { column_names }
column_names.each do |col_name|
define_singleton_method(col_name.to_sym) { columns[col_name] }
end
CSV.foreach(source_name, headers: true) do |row|
column_names.each do |col_name|
columns[col_name] << row[col_name]
end
end
end
end
feed = Feed.new('input.csv')
puts feed.columns # ["name", "age", "city"]
puts feed.name # ["Chris", "Tony"]
puts feed.age # ["43", "54"]
puts feed.city # ["Ohio", "NYC"]
feed2 = Feed.new('input.csv', ['name'])
puts feed2.columns # ["name"]
puts feed2.name # ["Chris", "Tony"]
请注意,我刚刚创建了 Feed
class 而不是 FeedGenerator
,因为我认为创建一个生成器没有多大意义,而您只需 initialize
方法。
另请注意,如果您只想在调用 feed.name
时从 CSV 文件中读取数据,那么所有 CSV 行都将存储在内存中(如果您的 CSV 非常大则效果不佳),例如,这是另一种方法:
require 'csv'
class Feed
def initialize(source_name, column_names = [])
if column_names.empty?
column_names = CSV.open(source_name, 'r', &:first)
end
define_singleton_method(:columns) { column_names }
column_names.each do |col_name|
define_singleton_method(col_name.to_sym) do
columns = []
CSV.foreach(source_name, headers: true) do |row|
columns << row[col_name]
end
columns
end
end
end
end
feed = Feed.new('input.csv')