2016-06-06 3 views
-1

логика, включенная в мой код ruby, немного сложна для перевода в вывод csv, есть ли способ добавить каждый value таким же образом, что print работает при выводе на терминал?вывод на csv аналогичным образом выводит вывод на терминал?

cop_log является хэш тысяч записей

cop_log = { 'A1' => 'val1', 'B1' => 'val2', 'C1' => 'val3', 'D1' => 'val4, 'E1' => 'val5', 'F1' => 'val6', 'G1' => 'val7', 'H1' => 'val8', 'I1' => 'val9', 'J1' => 'val10, 'K1' => 'val11', 'A2' => 'val12', 'B2' => 'val13', 'C2' => 'val14', 'D2' => 'val15, 'E2' => 'val16', 'F2' => 'val17', 'G2' => 'val18', 'H2' => 'val19', 'I2' => 'val20', 'J2' => 'val21, 'K2' => 'val22'} 

cop_log.each do |key, value| 
    if key.include?('K') 
    print "#{value}\n" 
    elsif key.include?('A') 
    print "#{job_number},#{pm_lookup[job_number]},#{value}," 
    elsif key.include?('B') || key.include?('C') || key.include?('D') || 
     key.include?('E') || key.include?('F') || key.include?('G') || 
     key.include?('H') || key.include?('I') || key.include?('J') 
    print "#{value}," 
    end 
end 

В настоящее время выходы в терминале, как это, я хочу, чтобы напечатать в CSV таким же образом:

val1, val2, val3, val4, val5, val6, val7, val8, val9, val10, val11 
val12, val13, val14, val15, val16, val17, val18, val19, val10, val21, val22 

чтение документации похоже, что общий маршрут заключается в следующем:

CSV.open("path/to/file.csv", "wb") do |csv| 
    csv << ["row", "of", "CSV", "data"] 
    csv << ["another", "row"] 
    # ... 
end 

К сожалению, s структура моего кода собирается сделать это немного трудным ....

+1

Как мы учимся API, мы склонны рисовать себя в углах и попытаться выйти из ситуации, желая изменить API, а не наш код. Лучше идти с потоком и использовать API по своему усмотрению. Вы найдете, что ваш код будет более читабельным. Как написано, ваш код не является идиоматичным и может быть переписан более четко. Я бы счел это возможностью рефакторинга. Что касается вашего «вопроса», вы его не спрашивали. Мы можем догадаться, что вы хотите помочь, но это поможет нам и другим, если вы более четко сформулируете свои цели. –

+0

Как выглядят ваши «клавиши»? Являются ли они единственными буквами, которые вы соответствуете, или пытаетесь найти буквы внутри строки? Пожалуйста, прочитайте «[ask]» и «[mcve]». Нам нужны минимальные входные данные и ожидаемый результат. –

+0

Благодарим вас за ваши комментарии и ответы, ключи взяты из хэша, собранного из таблицы Excel, используя драгоценный камень крик. вся таблица Excel находится внутри моего хэша, хеш-ключи - это каждая ячейка, такая как A1, B1, C1, A2, B2, C2 и т. д. мой код сортирует каждую строку. его для работы с конкретным шаблоном файла Excel, используемым в конкретной корпорации. Я переосмыслию свой подход. @theTinMan – aronlmin

ответ

0

Вы не могли бы это сделать?

CSV.open("path/to/file.csv", "wb") do |csv| 
    cop_log.each do |key, value| 
     if key.include?('A') 
      csv << [ job_number, pm_lookup[job_number], value ] 
     elsif key.include?('K') || key.include?('B') || key.include?('C') || key.include?('D') || 
      key.include?('E') || key.include?('F') || key.include?('G') || 
      key.include?('H') || key.include?('I') || key.include?('J') 
      csv << [ value ] 
     end 
    end 
end 
0
def write_csv(cop_log, io = $stdout) 
    cop_log.each do |key, value| 
    if key.include?('K') 
     io.print "#{value}\n" 
    elsif key.include?('A') 
     io.print "#{job_number},#{pm_lookup[job_number]},#{value}," 
    elsif key.include?('B') || key.include?('C') || key.include?('D') || 
      key.include?('E') || key.include?('F') || key.include?('G') || 
      key.include?('H') || key.include?('I') || key.include?('J') 
     io.print "#{value}," 
    end 
    end 
end 

Тогда

File.open('path/to/file.csv', 'w') do |f| 
    write_csv(cop_log, f) 
end 
1

Это очень сбивает с толку, и, если очищены, поможет сделать ваш код более читаемым и ремонтопригодны:

if key.include?('K') 
    print "#{value}\n" 
elsif key.include?('A') 
    print "#{job_number},#{pm_lookup[job_number]},#{value}," 
elsif key.include?('B') || key.include?('C') || key.include?('D') || 
    key.include?('E') || key.include?('F') || key.include?('G') || 
    key.include?('H') || key.include?('I') || key.include?('J') 
    print "#{value}," 
end 

Что такое key? Строка символов или один символ? Если вы одиночные символы, которые вы могли бы сделать что-то вроде:

if key == 'K' 
    print "#{value}\n" 
elsif key == 'A' 
    print "#{job_number},#{pm_lookup[job_number]},#{value}," 
elsif ('B'.. 'J').include?(key) 
elsif 
    print "#{value}," 
end 

и даже конвертировать:

elsif ('B'.. 'J').include?(key) 

к:

elsif ('B'..'J') === key 

Если вы ищете матч символов внутри строки:

if key['K'] 
    print "#{value}\n" 
elsif key['A'] 
    print "#{job_number},#{pm_lookup[job_number]},#{value}," 
elsif key[/[B-J]/] 
    print "#{value}," 
end 

На этом этапе вы готовы решить проблему очистки CSV-выхода. Я бы рекомендовал начать с использования одного из the basic examples вывода CSV в документации по классу. Я также рекомендовал бы внимательно прочитать «Comma-separated values», чтобы вы были более знакомы с ожиданиями файла формата CSV.

(Примечание: На данный момент входной образец хэш был добавлен вопрос, показывающий фактический формат ключей.)

Я дам вам понять, как включить CSV, но медитировать на этом:

cop_log = { 'A1' => 'val1', 'B1' => 'val2', 'C1' => 'val3', 'D1' => 'val4', 'E1' => 'val5', 'F1' => 'val6', 'G1' => 'val7', 'H1' => 'val8', 'I1' => 'val9', 'J1' => 'val10', 'K1' => 'val11', 'A2' => 'val12', 'B2' => 'val13', 'C2' => 'val14', 'D2' => 'val15', 'E2' => 'val16', 'F2' => 'val17', 'G2' => 'val18', 'H2' => 'val19', 'I2' => 'val20', 'J2' => 'val21', 'K2' => 'val22'} 
cop_log.values.each_slice(11) do |slice| 
    puts slice.join(',') 
end 

# >> val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,val11 
# >> val12,val13,val14,val15,val16,val17,val18,val19,val20,val21,val22 

Для создания CSV-файлов вам необходимо использовать CSV-класс; Формат не такой простой, как кажется.


Вот первый проход, как бы я написать код:

require 'csv' 

cop_log = { 'A1' => 'val1', 'B1' => 'val2', 'C1' => 'val3', 'D1' => 'val4', 'E1' => 'val5', 'F1' => 'val6', 'G1' => 'val7', 'H1' => 'val8', 'I1' => 'val9', 'J1' => 'val10', 'K1' => 'val11', 'A2' => 'val12', 'B2' => 'val13', 'C2' => 'val14', 'D2' => 'val15', 'E2' => 'val16', 'F2' => 'val17', 'G2' => 'val18', 'H2' => 'val19', 'I2' => 'val20', 'J2' => 'val21', 'K2' => 'val22'} 

job_number = 1 
pm_lookup = [0, 1] 

CSV.open('./foo.csv', 'w') do |csv| 
    cop_log.group_by{ |k, v| k[1] }.values.each do |row| 
    csv << [ job_number, pm_lookup[job_number], *row.map{ |k, v| v } ] 
    end 
end 

После запуска, foo.csv содержит:

1,1,val1,val2,val3,val4,val5,val6,val7,val8,val9,val10,val11 
1,1,val12,val13,val14,val15,val16,val17,val18,val19,val20,val21,val22 

Мы не знаем, что ваш ожидается выход , поскольку вы не сказали нам, но вы могли бы работать с этим кодом и понять это.

Вот ломка предварительной обработки данных:

cop_log.group_by{ |k, v| k[1] } # => {"1"=>[["A1", "val1"], ["B1", "val2"], ["C1", "val3"], ["D1", "val4"], ["E1", "val5"], ["F1", "val6"], ["G1", "val7"], ["H1", "val8"], ["I1", "val9"], ["J1", "val10"], ["K1", "val11"]], "2"=>[["A2", "val12"], ["B2", "val13"], ["C2", "val14"], ["D2", "val15"], ["E2", "val16"], ["F2", "val17"], ["G2", "val18"], ["H2", "val19"], ["I2", "val20"], ["J2", "val21"], ["K2", "val22"]]} 
     .values # => [[["A1", "val1"], ["B1", "val2"], ["C1", "val3"], ["D1", "val4"], ["E1", "val5"], ["F1", "val6"], ["G1", "val7"], ["H1", "val8"], ["I1", "val9"], ["J1", "val10"], ["K1", "val11"]], [["A2", "val12"], ["B2", "val13"], ["C2", "val14"], ["D2", "val15"], ["E2", "val16"], ["F2", "val17"], ["G2", "val18"], ["H2", "val19"], ["I2", "val20"], ["J2", "val21"], ["K2", "val22"]]] 

В коде выше я убедившись, что вход в ожидаемом порядке, в данном случае я группирования по одно- разрядных строк. Более надежный код будет использовать \d+ вместо 1, а также сортировать, чтобы заставить соответствующий порядок.

Это действительно важно, когда вы массируете данные из одного формата в другой для последующего повторного использования. Хотя текущие Rubies гарантируют, что хеш будет поддерживать свой порядок вставки, это не очень хорошая практика, поскольку старые версии Ruby этого не сделали, а на других языках вы переносите код, который может не поддерживать порядок. Вместо этого всегда защищайте программу, следя за тем, чтобы вы возвращали согласованные результаты. В какой степени вы это делаете, это то, что вы узнаете, когда узнаете о предыдущей попытке, было недостаточно. Программирование - это весело.

И, наконец, всякий раз, когда ваш код чувствует себя неловко или не течет, пришло время создать резервную копию и посмотреть, что вы делаете.

+0

К сожалению, каждый ключ - это номер пары букв, он поступает непосредственно из таблицы Excel, A1, B1, C1, A2, B2, C2 и т. Д., Спасибо за ответ, хотя – aronlmin

+0

Я добавил код, показывающий, как бы я это сделал , –

0

повторно Fector код

CSV.open("test.csv", "ab") do |csv| 
     b = {} 
     check_num = 0 
     cop_log.each do |key, value| 
     num = key.gsub(/[^\d]/, '').to_i 
     next if num < 8 || 
       key.include?('L') || key.include?('M') || key.include?('N') || 
       key.include?('O') || key.include?('P') || key.include?('Q') || 
       key.include?('R') || key.include?('S') || key.include?('T') || 
       key.include?('U') || key.include?('V') 
     a = { key => value } 
     b.merge!(a) 
     end # end of each loop 
     i = 8 
     while ((b.length/9) - 7) > i do 
     csv << [ job_number, pm_lookup[job_number], b["A#{i}"], b["B#{i}"], 
       b["C#{i}"], b["D#{i}"], b["E#{i}"], b["F#{i}"], b["G#{i}"], 
       b["H#{i}"], b["I#{i}"], b["J#{i}"], b["K#{i}"] ] 
     i += 1 
     end 
    end # end of CSV.open 
Смежные вопросы