2013-08-08 35 views
5

Tất cả những gì tôi cần làm là lấy tiêu đề từ tệp CSV.Cách dễ nhất để lấy tiêu đề từ tệp CSV trong Ruby là gì?

file.csv là:

"A", "B", "C" 
"1", "2", "3" 

Mã của tôi là:

table = CSV.open("file.csv", :headers => true) 

puts table.headers 

table.each do |row| 
    puts row 
end 

nào mang lại cho tôi:

true 
"1", "2", "3" 

Tôi đã nhìn vào tài liệu của Ruby CSV trong nhiều giờ và điều này khiến tôi điên mất. Tôi tin rằng phải có một lớp lót đơn giản có thể trả lại tiêu đề cho tôi. Bất kỳ ý tưởng?

Trả lời

11

Dường như CSV.read sẽ cung cấp cho bạn truy cập đến một phương pháp headers:

headers = CSV.read("file.csv", headers: true).headers 
# => ["A", "B", "C"] 

Trên đây thực sự chỉ là một phím tắt cho CSV.open("file.csv", headers: true).read.headers. Bạn có thể đã nhận được nó bằng cách sử dụng CSV.open như bạn đã thử, nhưng kể từ khi CSV.open không thực sự đọc các tập tin khi bạn gọi phương pháp, không có cách nào cho nó để biết những gì các tiêu đề cho đến khi nó thực sự đọc một số dữ liệu. Đây là lý do tại sao nó chỉ trả lại true trong ví dụ của bạn. Sau khi đọc một số dữ liệu, nó cuối cùng sẽ trở lại tiêu đề:

table = CSV.open("file.csv", :headers => true) 
    table.headers 
    # => true 
    table.read 
    # => #<CSV::Table mode:col_or_row row_count:2> 
    table.headers 
    # => ["A", "B", "C"] 
0

Nếu bạn muốn có một câu trả lời ngắn sau đó có thể thử:

headers = CSV.open("file.csv", &:readline) 
# => ["A", "B", "C"] 
+0

Thông tin cần biết nhưng tôi muốn lựa chọn cho môi trường 'cách tiếp cận .headers' rõ ràng hơn rằng @ Dylan-Markow gợi ý. –

3

Theo tôi cách tốt nhất để làm điều này là:

headers = CSV.foreach('file.csv').first

Xin lưu ý rằng nó rất hấp dẫn để sử dụng CSV.read('file.csv'. headers: true).headers nhưng bắt là, CSV.read tải tệp hoàn chỉnh trong bộ nhớ và do đó inc cho thuê bộ nhớ của bạn và cũng như nó làm cho nó rất chậm để sử dụng cho các tập tin lớn hơn. Bất cứ khi nào có thể, vui lòng sử dụng CSV.foreach. Dưới đây là điểm chuẩn cho chỉ là một tập tin 20 MB:

Ruby version: ruby 2.4.1p111 
File size: 20M 
**************** 
Time and memory usage with CSV.foreach: 
Time: 0.0 seconds 
Memory: 0.04 MB 
**************** 
Time and memory usage with CSV.read: 
Time: 5.88 seconds 
Memory: 314.25 MB 

Một tập tin 20MB tăng bộ nhớ bằng 314 MB với CSV.read tưởng tượng những gì một tập tin 1GB. Trong ngắn hạn xin vui lòng không sử dụng CSV.read, tôi đã làm và hệ thống đã đi xuống cho một tập tin 300MB.

Để đọc thêm: Nếu bạn muốn đọc thêm về điều này, here là một bài viết rất hay về cách xử lý các tệp lớn.

Ngoài ra dưới đây là kịch bản tôi sử dụng cho điểm chuẩn CSV.foreachCSV.read:

require 'benchmark' 
require 'csv' 
def print_memory_usage 
    memory_before = `ps -o rss= -p #{Process.pid}`.to_i 
    yield 
    memory_after = `ps -o rss= -p #{Process.pid}`.to_i 
    puts "Memory: #{((memory_after - memory_before)/1024.0).round(2)} MB" 
end 

def print_time_spent 
    time = Benchmark.realtime do 
    yield 
    end 
    puts "Time: #{time.round(2)} seconds" 
end 

file_path = '{path_to_csv_file}' 
puts 'Ruby version: ' + `ruby -v` 
puts 'File size:' + `du -h #{file_path}` 
puts 'Time and memory usage with CSV.foreach: ' 
print_memory_usage do 
    print_time_spent do 
    headers = CSV.foreach(file_path, headers: false).first 
    end 
end 
puts 'Time and memory usage with CSV.read:' 
print_memory_usage do 
    print_time_spent do 
    headers = CSV.read(file_path, headers: true).headers 
    end 
end 
Các vấn đề liên quan