2013-08-08 21 views
5

Tek yapmam gereken, başlıkların bir CSV dosyasından alınmasıdır.Başlıkları Ruby'deki bir CSV dosyasından almanın en kolay yolu nedir?

file.csv geçerli:

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

Benim kodudur:

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

saatlerce Yakut CSV belgelerine bakarak oldum ve:

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

puts table.headers 

table.each do |row| 
    puts row 
end 

bana verir Hangi Bu beni deli ediyor. Başlıkları bana iade edebilecek basit bir tek liner olması gerektiğine inanıyorum. Herhangi bir fikir? Yukarıdaki

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

gerçekten CSV.open("file.csv", headers: true).read.headers için sadece bir kısayoldur:

cevap

11

Bu bir headers yönteme erişim sağlayacak CSV.read benziyor. Denediğiniz gibi, CSV.open'u kullanarak kazanmış olabilirsiniz, ancak metodu çağırdığınızda CSV.open aslında dosyayı okumadığından, aslında bazı verileri okuyana kadar başlıkların ne olduğunu bilmenin bir yolu yoktur. Bu yüzden, örneğinizde true değerini döndürüyor. Daha kısa bir cevap daha sonra deneyebilirsiniz isterseniz

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

: bazı verileri okuduktan sonra, sonunda başlıkları döneceğini Bence

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

İyi bilmek ama @ Dylan-Markov da anlaşılacağı daha açıkça '.headers' yaklaşımın tercih olacaktır. –

3

Bunu yapmanın en iyi yolu geçerli:

dolayısıyla hafıza ve içinde

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

onun çok cazip CSV.read('file.csv'. headers: true).headers kullanmak lütfen unutmayın ama yakalamak olduğunu CSV.read yükler komple dosyasını inc bellek ayak izinizi arttırır ve ayrıca büyük dosyalar için kullanılmasını çok yavaşlatır. Mümkün olduğunda lütfen CSV.foreach'u kullanın. Aşağıda sadece 20 MB dosya için kriterler şunlardır:

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 

CSV.read ile 314 MB tarafından yapılan bir 20MB dosya artışı bellek izi ne 1GB dosya düşünün. Kısacası lütfen CSV.read'u kullanmayın, yaptım ve sistem 300MB'lık bir dosya için aşağı indi.

Daha fazla okumak için: Bu konuda daha fazla bilgi edinmek isterseniz, here büyük dosyaları işlemek için çok iyi bir makaledir.

Ayrıca aşağıda i CSV.foreach ve CSV.read benchmarking için kullanılan script:

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 
İlgili konular