2017-02-17 10 views
1

У меня есть CSV с основным списком людей, их пола и возраста, а также соответствующие заголовки:Фильтрация в новый CSV с заголовками в Ruby?

"First Name","Age","Gender" 
"Adam",31,"Male" 
"Bruce",36,"Male" 
"Lawrence",34,"Male" 
"James",32,"Male" 
"Elyse",30,"Female" 
"Matt",32,"Male" 

Я хотел бы, чтобы открыть этот файл CSV в Ruby, пройти по строчкам, и приложить все мужчин в новый CSV с теми же заголовками и сохранить этот CSV в новый файл.

Мой код прямо сейчас (не работает)

require 'csv' 

file = 'cast.csv' 

new_cast = CSV.new(:headers => CSV.read(file, :headers => :true).headers) 

CSV.foreach(file, :headers => :true, :header_converters => :symbol) do |row| 
    if row[:gender] == 'Male' 
     new_cast.add_row(row) 
    end 
end 

File.open('new_cast.csv', 'w') do |f| 
    f.write(new_cast) 
end 

Сообщение об ошибке я получаю:

/usr/local/Cellar/ruby/2.3.0/lib/ruby/2.3.0/csv.rb:1692:in `<<': undefined method `<<' for {:headers=>["First Name", "Age", "Gender"]}:Hash (NoMethodError) 
Did you mean? < 
    from csv.rb:8:in `block in <main>' 
    from /usr/local/Cellar/ruby/2.3.0/lib/ruby/2.3.0/csv.rb:1748:in `each' 
    from /usr/local/Cellar/ruby/2.3.0/lib/ruby/2.3.0/csv.rb:1131:in `block in foreach' 
    from /usr/local/Cellar/ruby/2.3.0/lib/ruby/2.3.0/csv.rb:1282:in `open' 
    from /usr/local/Cellar/ruby/2.3.0/lib/ruby/2.3.0/csv.rb:1130:in `foreach' 
    from csv.rb:6:in `<main>' 

Итак, похоже, что я делаю что-то очень неправильно. Каким будет самый простой способ сделать это?

ответ

0

CSV#new принимает в качестве своего первого аргумента «объект string или IO», а необязательный хеш - второй, per the docs.

Так это выглядит как ошибка на самом деле вызвана этой линией:

new_cast = CSV.new(:headers => CSV.read(file, :headers => :true).headers) 

, который должен быть

new_cast = CSV.new("", :headers => CSV.read(file, :headers => :true).headers) 

Примечания пустой строки.

Но даже при этом это не будет писать новый CSV. Для этого я думаю, что вы хотите write_headers в своем новом CSV, а затем rewind перед тем, как писать, подвергая лежащему в основе IO object.

require 'csv' 

file = 'cast.csv' 

new_cast = CSV.new("", :headers => CSV.read(file, :headers => :true).headers, write_headers: true) 

CSV.foreach(file, :headers => :true, :header_converters => :symbol) do |row| 
    if row[:gender] == 'Male' 
    new_cast.add_row(row) 
    end 
end 

CSV.open('new_cast.csv', 'w') do |csv| 
    new_cast.rewind 
    new_cast.each {|row| csv << row} 
end 

Надеюсь, что это поможет!