2013-05-10 2 views
0

Предположим, у меня есть файл в следующем формате.Проверьте заголовок файла, а затем выполните цикл

date|time|account 
2010-01-01|07:00:00|A1 
2010-01-01|07:00:01|A2 
.... 

Предположим, у меня есть следующая функция.

def ReadLongFile(longFile) 
    CSV.foreach(longFile, :headers => true, :col_sep => '|') do |row| 
    p row.to_hash 
    end 
end 

Мне нравится эта функция, поскольку она позволяет мне хранить каждую строку как хэш, где элементы заголовка являются ключами, а элементы строки соответствующих значений. Однако, каков наиболее эффективный способ его изменения, чтобы я мог проверить, что заголовок содержит правильные записи? Я рассматривал два варианта. Во-первых, я мог бы открыть еще одну функцию и проверить первую строку. Во-вторых, я мог бы проверить внутри функции, но он будет выполнять проверку каждой итерации.

ответ

1

Я бы предложил использовать функцию CSV::header_row для выполнения проверки и поднять ошибку, если это не то, что вы ожидаете. Что-то вроде:

def ReadLongFile(longFile) 
    CSV.foreach(longFile, :headers => true, :return_headers => true, :col_sep => '|') do |row| 
    if row.header_row? then 
     raise ArgumentError, "Bad headers" unless header_sane?(row) 
    end 
    # Otherwise do the processing 
    end 
end 

Ваш header_sane? реализации внешних выполнит проверку, что вам нужно, чтобы убедиться, что файл, что вы ожидаете, что это будет. Ваш код вызова может спасти ArgumentError, если он может восстановиться из него, или просто дать ему сбой :-)

Примечание: Обновлено, чтобы отразить ошибку, указанную в комментариях ниже. Обязательно установите опцию: return_headers при вызове CSV::foreach.

Если вы беспокоитесь о минимальных издержках вызова header_row? для каждой записи строки вы можете создать экземпляр CSV и использовать shift для ручной проверки первой строки перед продолжением. Например:

def ReadLongFile(longFile) 
    File.open(longFile) do |file| 
    reader = CSV.new(file, {:col_sep => '|', :headers => true, :return_headers => true}) 
    header_row = reader.shift 
    raise ArgumentError, "Bad file headers" unless header_sane?(header_row) 
    reader.each do |row| 
     p row 
    end 
    end 
end 

Реализовано, как указано выше, следующее поведение справедливо:

[4] pry(main)> def header_sane? row 
[4] pry(main)* true 
[4] pry(main)* end 
=> nil 
[5] pry(main)> ReadLongFile("file.csv") 
#<CSV::Row "date":"2010-01-01" "time":"07:00:00" "account":"A1"> 
#<CSV::Row "date":"2010-01-01" "time":"07:00:01" "account":"A2"> 
=> nil 
[6] pry(main)> def header_sane? row 
[6] pry(main)* false 
[6] pry(main)* end 
=> nil 
[7] pry(main)> ReadLongFile("file.csv") 
ArgumentError: Bad file headers 
from (pry):7:in `block in ReadLongFile' 
+0

Это неправильно. Первый 'is_header?' В вашей функции должен быть 'header_row?'. Кроме того, необходимо установить ': return_headers' значение true. – idealistikz

+1

@idealistikz соответственно обновлено - спасибо! –

Смежные вопросы