Ruby - 读取 .csv 并从中创建对象

标签 ruby csv

我有 .csv 文件,其中每行代表一个具有特定持续时间、数量等的调用。我需要创建 Call 对象数组 - 每个 Call.new 都需要参数的哈希值,所以这很容易 - 只需要行来自 CSV。但由于某种原因它不起作用 - 当我调用 Call.new(raw_call) 时它是 nil 。 我也不可能看到任何输出 - 我将 puts 放置在代码中的各个位置( block 内等),但它根本不显示任何内容。我显然有另一个类 - Call,它保存 Call 等的初始化。

require 'csv'
class CSVCallParser
  attr_accessor :io

  def initialize(io)
    self.io = io
  end

  NAMES = {
    a: :date,
    b: :service,
    c: :phone_number,
    d: :duration,
    e: :unit,
    f: :cost
  }

  def run
    parse do |raw_call| 
    parse_call(raw_call)
    end
  end

  private

  def parse_call(raw_call) 
    NAMES.each_with_object({}) do |name, title, memo|
      memo[name] = raw_call[title.to_s]
    end
  end

  def parse(&block) 
    CSV.parse(io, headers: true, header_converters: :symbol, &block)
  end

end

CSVCallParser.new(ARGV[0]).run

我的 .csv 文件的小样本:标题和一行:

"a","b","c","d","e","f"
"01.09.2016 08:49","International","48627843111","0:29","","0,00"

最佳答案

我注意到一些事情没有按预期进行。在 parse_call 方法中,

def parse_call(raw_call) 
  NAMES.each_with_object({}) do |name, title, memo|
    memo[name] = raw_call[title.to_s]
  end
end

我尝试打印nametitlememo。我期望得到 :a:date{},但实际得到的是 [:a,:date ]{}nil

此外,raw_call header 是 :a,:b,:c...,而不是 :date, :service... ,因此您应该使用 raw_call[name],并将其转换为字符串不会有帮助,因为键是 raw_call 中的符号。

所以我将函数修改为

def parse_call(raw_call) 
  NAMES.each_with_object({}) do |name_title, memo|
    memo[name_title[1]] = raw_call[name_title[0]]
  end
end

name_title[1] 返回标题(:date:service 等)

name_title[0] 返回名称(:a:b 等)

另外,在这个方法中

def run
  parse do |raw_call| 
    parse_call(raw_call)
  end
end

您没有返回得到的任何结果,因此您得到的是nil

所以我把它改成了

  def run
    res = []
    parse do |raw_call| 
      res << parse_call(raw_call)
    end
    res 
  end

现在,如果我输出该行

p CSVCallParser.new(File.read("file1.csv")).run

我明白了(我在 csv 示例中又添加了两行)

[{:date=>"01.09.2016 08:49", :service=>"International", :phone_number=>"48627843111", :duration=>"0:29", :unit=>"", :cost=>"0,00"},
 {:date=>"02.09.2016 08:49", :service=>"International", :phone_number=>"48622454111", :duration=>"1:29", :unit=>"", :cost=>"0,00"}, 
 {:date=>"03.09.2016 08:49", :service=>"Domestic", :phone_number=>"48627843111", :duration=>"0:29", :unit=>"", :cost=>"0,00"}]

如果你想像这样从终端运行这个程序

ruby csv_call_parser.rb calls.csv

(在本例中,calls.csv 作为参数传递给 ARGV)

您可以通过修改 ruby​​ 文件的最后一行来实现此目的。

p CSVCallParser.new(File.read(ARGV[0])).run

这也将像以前一样返回带有哈希值的数组。

关于Ruby - 读取 .csv 并从中创建对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39874886/

相关文章:

ruby - Shotgun Gem 的问题 - RuntimeError

ruby-on-rails - YAML::load 引发未定义的类/模块错误

读取并绑定(bind)多个 csv 文件

XML 到 CSV 应用 XSLT(格式问题、逻辑错误)

java - 如何在jmeter中捕获响应数据并进行参数化

ruby - 更改 ActiveRecord 中对象的类

arrays - &-> 在 ruby​​ 中是什么意思

ruby - 优秀而简单的 Ruby XML 编写器?

r - 使用 R 将表写入文件会导致不需要的行名称列

c# - 第一行未从 csv 导入到 DataTable 中