Используя Рубин, чтобы заменить определенные отчеты в файле CSV с отчетами из другого файла CSV

У меня есть два файла CSV большого выхода. Один файл - просто список отчетов. Другой файл - список отчетов, но первая колонка - номер строки отчета, который это изменяет в другом файле. Это не заменяет целый ряд; Это просто заменяет стоимость в ряду, у которого есть соответствующий заголовок.

Например:

Файл 1:

"First","Last","Lang"
"John","Doe","Ruby"
"Jane","Doe","Perl"
"Dane","Joe","Lisp"

Файл 2:

"Seq","Lang"
2,"Ruby"

Цель состоит в том, чтобы закончиться с одним файлом, который похож на это:

"First","Last","Lang"
"John","Doe","Ruby"
"Jane","Doe","Ruby"
"Dane","Joe","Lisp"

Данные, однако, намного более сложны, чем это и могли даже содержать разрывы строки в CSV. Таким образом я не могу полагаться на номер строки, и вместо этого я должен полагаться на количество записей. (Если, конечно, я не предварительно обрабатываю и файлы, чтобы заменить новые строки и возвраты каретки.. то, которое я предполагаю, возможно, но менее интересно.)

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

Кроме того, отчеты в получающемся файле должны быть в <�сильном> то же самое </сильны> заказ, когда это сделано.

0
добавлено отредактировано
Просмотры: 1
de
Предположение этих закодированных рукой файлов CSV? Я принимаю, потому что вы обертываете каждую последовательность в " когда that' s абсолютно ненужный для ценностей you' ve обеспечивается.
добавлено автор maček, источник
Файл 2' s ' Seq' колонка в заказе?
добавлено автор pguardiario, источник
Я просто впечатал примеры вручную. В случае реальных файлов, одного из них doesn' t используют кавычки если необходимый и другие кавычки сил. CSV должен разобрать их так или иначе, с или без кавычек.
добавлено автор Jeremy Baker, источник
pguardiario: Да, это должно всегда быть в порядке.
добавлено автор Jeremy Baker, источник

2 ответы

Это в основном, как я обращался бы с ним, если бы файлы были слишком большими, чтобы загрузить в память

// pseudocode

f1 = fopen(file1)
f2 = fopen(file2)
f3 = fopen(newfile)

// loop through exceptions
foreach row2, index2 of f2

 //loop through file1 until a matched row is found
  while (row1, index1 of f1) && (row1 not null) && (row2[seq] <= index1)

   //patch
    if row2[seq] == index1
      row1[lang] = row2[lang]
    endif

   //write out to new file
    f3.write row1

  endwhile
endforeach

† Начиная с вашего file2 имеет 1 - базирующиеся индексы (вместо того, чтобы быть 0 - базирующийся), вы захотите начать ваш index1 и index2 прилавки в 1 .


†† Если lang не будет колонкой, то вы будете всегда заменять:

// at the beginning of the foreach loop
if col is null
  cols = array_keys row2
  col = cols[2]//1-based index
end

// the new patch block
if row2[seq] == index1
  row1[col] = row2[col]
endif

1
добавлено

Вам будут нужны 2 счетчика, но так как они не вложены, нужно будет использовать Enumerator#next, что означает, что необходимо быть осторожны относительно этого поднимающий исключение EOF:

e = CSV.open('file2.csv', :headers => true).each
seq = e.next

output = CSV.open('output.csv', 'w')

csv = CSV.open('file1.csv')
csv.each do |row|
  if seq['Seq'].to_i == csv.lineno - 1
    row[2] = seq['Lang']
    seq = e.next rescue ({'Seq' => -1})
  end
  output << row
end
1
добавлено