Разбор CSV файла. Разделение на большее количество файлов

В настоящее время я работаю над небольшим приложением, которое позволит кому-то вводить строки, которые будут разделять больший файл на более мелкие файлы.

У меня возникла проблема с тем, чтобы файл был разделен на более новые файлы. Это мой код для моего метода CSV:

require 'csv'
new_list = []
old_list = []
def import_csv(file) puts "Method begins" CSV.foreach("public_schools_list.csv", :encoding => 'windows-1251:utf-8', :headers => true) do |row| if row["company"].downcase.include?("academy" || "lutheran" || "jewish" || "private" || "christian") CSV.open("new_list.csv", "ab") do |n| n << row puts "First Row" new_list << n end else CSV.open("old_list.csv", "ab") do |o| o << row puts "Second Row" old_list << o end end end
end
puts "New Csv: #{new_list.count}"
puts "Old Csv: #{old_list.count}"

Я просто пытаюсь проверить этот код, чтобы увидеть, разделяет ли он файлы. Я не уверен, что некоторые из них верны. В настоящее время в списке CSV есть только четыре элемента. Я использую метод count чтобы проверить, попадают ли они в правильные файлы.

Какой код мне не хватает, чтобы разделить главный файл на два?

вот мой контроллер:

include CSVUpload
def import csv_separate(params[:file].tempfile) redirect_to root_url
end

то вот модуль, который я использую:

require 'csv'
module CSVUpload def csv_separate(file) new_list_counter = 0 old_list_counter = 0 # puts "Method begins" CSV.open("new_list.csv", "ab") do |new_list| CSV.open("old_list.csv", "ab") do |old_list| CSV.foreach(file, :encoding => 'windows-1251:utf-8', :headers => true) do |row| if row["company"][/\b(?:academy|lutheran|jewish|private|christian)\b/i] new_list << row new_list_counter += 1 else old_list << row old_list_counter += 1 end end end end end end

а затем вот форма:

<div> <h3>Import a CSV File</h3> <%= form_tag({action: "import"}, multipart: true) do %> <%= file_field_tag("file") %> <%= submit_tag "Import CSV" %> <% end %>
</div>

Я надеюсь, что это поможет немного. Благодарю!

1 ответ

Не открывайте и закрывайте выходные файлы для каждой прочитанной строки. Это ужасно неэффективно и тратит процессорное время. Откройте их вне цикла CSV.foreach, а затем напишите им условно.

Кроме того, не суммируйте строки файла в памяти, чтобы вы могли их подсчитать. Вместо этого увеличивайте счетчик.

Кроме того, include? не работает таким образом:

include?("academy" || "lutheran" || "jewish" || "private" || "christian")

В документации говорится:

str.include? other_str -> true or false
------------------------------------------------------------------------------
Returns true if str contains the given string orcharacter. "hello".include? "lo" #=> true "hello".include? "ol" #=> false "hello".include? ?h #=> true

Обратите внимание, что для этого требуется один символ или строка. Использование списка or'd строк приводит только к первой строке:

"academy" || "lutheran" || "jewish" || "private" || "christian" # => "academy"

В результате, только "академия" была бы проверена на предмет включения.

Это не проверено, но выглядит достаточно верно:

require 'csv'
def import_csv(file) new_list_counter = 0 old_list_counter = 0 puts "Method begins" CSV.open("new_list.csv", "ab") do |new_list| CSV.open("old_list.csv", "ab") do |old_list| CSV.foreach("public_schools_list.csv", :encoding => 'windows-1251:utf-8', :headers => true) do |row| if row["company"][/\b(?:academy|lutheran|jewish|private|christian)\b/i] new_list << row puts "First Row" new_list_counter += 1 else old_list << row puts "Second Row" old_list_counter += 1 end end end end puts "New CSV: #{ new_list_counter }" puts "Old CSV: #{ old_list_counter }"
end

Уведомление /\b(?:academy|lutheran|jewish|private|christian)\b/i. Это проверяет несколько подстрок, которые являются полными словами. \b в regex-ese означает "слово-граница", поэтому каждый из встроенных слов или'd вместе использует | тестируются отдельно. /i означает, что он не учитывает регистр. Чтобы выполнить то же самое, используя include? будет включать цикл за списком слов, который является одним из тех алгоритмов, который растет медленнее и медленнее, когда вы добавляете больше слов для тестирования.

row["company"][/\b(?:academy|lutheran|jewish|private|christian)\b/i] чрезвычайно эффективен по сравнению с этим возможным алгоритмом цикла. Использование шаблонов регулярных выражений не является универсальной панацеей. Использованные неправильные шаблоны регулярных выражений могут фактически замедлить вашу программу, а иногда и резко. Правильно используются, но они могут уменьшить ваш код и в правильной ситуации, когда они написаны правильно, могут значительно улучшить скорость. Итак, проверьте, используя тесты, прежде чем вслепую ввести их в код.

licensed under cc by-sa 3.0 with attribution.