Ruby 以类似的方式输出到csv';打印';输出到终端?

Ruby 以类似的方式输出到csv';打印';输出到终端?,ruby,csv,Ruby,Csv,我的ruby代码中包含的逻辑很难转换为csv输出,是否有一种方法可以将每个值以类似于打印输出到终端时的方式追加 cop_日志是数千条记录的散列 cop_log = { 'A1' => 'val1', 'B1' => 'val2', 'C1' => 'val3', 'D1' => 'val4, 'E1' => 'val5', 'F1' => 'val6', 'G1' => 'val7', 'H1' => 'val8', 'I1' => 'val

我的ruby代码中包含的逻辑很难转换为csv输出,是否有一种方法可以将每个
以类似于
打印
输出到终端时的方式追加

cop_日志是数千条记录的散列

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
CSV.open(“path/to/file.CSV”、“wb”)do|CSV|
csv你不能这样做吗

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
CSV.open(“path/to/file.CSV”、“wb”)do|CSV|
cop_log.each do|键、值|
if键。包括?('A')
csv
然后


这非常混乱,如果清理干净,将有助于使代码更具可读性和可维护性:

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
什么是
?字符串还是单个字符?如果要匹配单个字符,可以执行以下操作:

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)
致:

如果要在字符串中搜索字符匹配:

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输出。我建议重新开始使用类文档中的CSV输出之一。我还建议您仔细阅读“”,以便更熟悉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
我们不知道您的预期输出是什么,因为您没有告诉我们,但是您可以从代码中找到它

下面是数据预处理的分解:

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
,并且还会排序以强制执行适当的顺序

当您将数据从一种格式转换为另一种格式以供以后重用时,这一点非常重要。虽然当前的Ruby保证哈希将保持其插入顺序,但假设旧版本的Ruby没有这样做,并且您将代码移植到的其他语言可能无法保持顺序,这不是一个好的实践。相反,总是防御性地编程,确保返回一致的结果。当你发现以前的尝试是不够的时,你会知道你在多大程度上做到了这一点。这样编程很有趣

最后,当您的代码感到尴尬或无法流畅时,是时候备份并查看您正在做的事情了

完善代码

    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
CSV.open(“test.CSV”、“ab”)do | CSV|
b={}
检查\u num=0
cop_log.each do|键、值|
num=key.gsub(/[^\d]/,'')。到
如果num<8,则下一步||
键。包括('L')| |键。包括('M')| |键。包括('N'))||
键。包括('O')| |键。包括('P')| |键。包括('Q'))||
键。包括('R')| |键。包括('S')| |键。包括('T'))||
键。包括('U')| |键。包括('V'))
a={key=>value}
b、 合并!(a)
结束#每个循环的结束
i=8
而((b.length/9)-7)>我知道

csv当我们学习API时,我们倾向于把自己画进角落,试图通过改变API而不是代码来摆脱困境。最好按照流程进行,并按照预期使用API。你会发现你的代码更可读。正如所写的,您的代码不是惯用的,可以更清楚地重写。我认为这是一个重构的机会。至于你的“问题”,你一个也没问。我们可以猜到你需要帮助,但如果你能更清楚地说明你的目标,这对我们和其他人都有帮助。你的
键是什么样子的?它们是您正在匹配的单个字母,还是您正在尝试查找字符串中的字母?请阅读“及”。我们需要最少的输入数据和预期的输出。感谢您的评论和回答,这些键来自使用creek gem从excel电子表格编译而成的散列。整个excel电子表格都在我的散列中,散列键是每个单元格,如A1、B1、C1、A2、B2、C2等。我的代码是对每一行进行排序。它用于处理特定公司使用的特定excel文件模板。我会重新考虑我的方法@这个信息需要输入到你的问题中,就像你最初指定的那样。编辑问题,将信息添加到你想要的地方,这样一切都有意义。不要使用“编辑”或“更新”标记,因为我们可以知道在使用SO的编辑历史记录时添加了什么。不幸的是,每个键都是一个字母数字对,它直接来自excel电子表格,A1、B1、C1、A2、B2、C2等,谢谢您的回复
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
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"]]]
    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