2013-08-08 7 views
5

Alles, was ich tun muss, ist die Header aus einer CSV-Datei zu bekommen.Was ist der einfachste Weg, um die Header aus einer CSV-Datei in Ruby zu erhalten?

file.csv ist:

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

Mein Code ist:

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

puts table.headers 

table.each do |row| 
    puts row 
end 

Was gibt mir:

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

Ich habe Ruby CSV Dokumentation stundenlang suchen und das macht mich verrückt. Ich bin überzeugt, dass es einen einfachen Einliner geben muss, der mir die Header zurückgeben kann. Irgendwelche Ideen?

Antwort

11

Es sieht aus wie CSV.read werden Sie auf eine headers Methode zuzugreifen:

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

Die oben ist wirklich nur eine Abkürzung für CSV.open("file.csv", headers: true).read.headers. Sie könnten es mit CSV.open wie Sie versucht haben, aber seit CSV.open nicht tatsächlich die Datei lesen, wenn Sie die Methode aufrufen, gibt es keine Möglichkeit für sie zu wissen, was die Header sind, bis es tatsächlich einige Daten gelesen wird. Aus diesem Grund gibt es in Ihrem Beispiel einfach true zurück. Nach ein paar Daten zu lesen, wäre es schließlich die Header zurück:

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

Wenn Sie eine kürzere Antwort wollen, dann versuchen:

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

Gut zu wissen, aber ich würde für die explizitere '.headers' Ansatz entscheiden, dass @ Dylan-Markow vermuten lässt. –

3

Meiner Meinung nach der beste Weg, dies zu tun ist:

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

Bitte beachten Sie, dass seine sehr verlockend CSV.read('file.csv'. headers: true).headers zu verwenden, aber der Haken ist, CSV.read lädt komplette Datei im Speicher und damit inc verringert den Speicherbedarf und macht die Verwendung für größere Dateien auch sehr langsam. Wann immer möglich, benutzen Sie bitte CSV.foreach. Im Folgenden sind die Benchmarks für nur 20 MB-Datei:

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 

A 20MB Datei Erhöhung Speicherbedarf von 314 MB mit CSV.read vorstellen, was eine 1 GB-Datei. Kurz gesagt, verwenden Sie bitte nicht CSV.read, ich tat und System ging für eine 300 MB-Datei.

Für weitere Informationen: Wenn Sie mehr darüber lesen möchten, ist here ein sehr guter Artikel über die Handhabung großer Dateien.

unten Auch ist das Skript i für CSV.foreach Benchmarking verwendet und CSV.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 
Verwandte Themen