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

时间:2016-10-05 13:09:31

标签: ruby csv

我有.csv文件,其行每行代表一次具有特定持续时间,数字等的调用。我需要创建Call对象的数组 - 每个Call.new都需要Hash参数,所以很容易 - 它只需从CSV中获取行。但由于某些原因,当我调用Call.new(raw_call) nil时,它无法正常工作。 我也不可能看到任何输出 - 我将puts放在代码中的不同位置(内部块等)并且它根本不显示任何内容。我显然还有另一个类 - 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"

1 个答案:

答案 0 :(得分:2)

我注意到一些事情没有按预期进行。在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标头为: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

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