【问题标题】:Ruby parse csv by header valuesRuby 通过标头值解析 csv
【发布时间】:2012-09-18 11:25:31
【问题描述】:

我正在研究一种获取 CSV 文件(带有标题)并使用 Ruby CSV.parse 解析它的方法,但是我只想保存特定的列。

CSV 如下所示:

NAME,SUPERNET_IP,POP_NAME,ADDRESS_BLOCK_START,ADDRESS_BLOCK_END,Service,ISP Service ID,WCC,DUNSID
Retail,186.43.168.0,text1,186.43.168.0,186.43.175.255,XYZ,XYZB00090095,Enabled,227015716
Retail,186.57.80.0,text2,186.57.80.0,186.57.87.255,XYZ,XYXB00090095,Enabled,227015716

我想保留的唯一字段是:

POP_NAME,ADDRESS_BLOCK_START,ADDRESS_BLOCK_END,WCC

有没有办法通过特定的标题名称解析 CSV,例如:

mycsv = CSV.parse(csv_data, {:headers => true, (list of headers to keep here) })

此示例假设 csv_data 是由上述示例 CSV 形成的字符串。

作为权宜之计,我只是将 CSV 转换为数组数组,但这并不是我真正想要的。我宁愿将其保留为 CSV 对象。

myreturnedcsv = []
mycsv = CSV.parse(csv_data, {:headers => true, })
mycsv.each do |row|
  myreturnedcsv.push([row[2], row[3], row[4],row[7]])
end

【问题讨论】:

标签: ruby-on-rails ruby csv


【解决方案1】:

请尝试smarter_csv gem / 解析器。这可以忽略输入中的“列”(删除列)https://github.com/tilo/smarter_csv

【讨论】:

  • 如果我可以使用它来验证标头值,这似乎有用吗?
  • 使用 SmarterCSV.process 选项:key_mapping。文档说 -> 将 CSV 文件中的标头映射到结果哈希中的键的哈希。让我知道它是否适合您。
  • 只需在 :key_mapping 哈希中映射您不想 nil 的任何列
【解决方案2】:

仅使用stdlib,可以在列模式下操作CSV::Table对象 (而不是默认的混合模式)。在列模式下,迭代方法 将产生两个包含列名和值数组的元素元组 为该列。

考虑到这一点,我们可以这样写:

# column names to keep
columns_to_keep = %w(POP_NAME ADDRESS_BLOCK_START ADDRESS_BLOCK_END WCC)

# get the data
mycsv = CSV.parse(csv_data, :headers => true)

# change to column mode, filter by column name and change back to default
# mode of operation
mycsv.by_col!.delete_if do |col_name, col_values|
  !columns_to_keep.include?(col_name)
end.by_col_or_row!   

最后一步是可选的,只是让表格对象保持默认模式 我们可以像往常一样(按行)在其中迭代。

我实际上不知道这种方法是否会遇到性能/内存问题 处理大型数据集。

您可以在CSV::Table 的文档中找到有关行/列/混合访问的更多信息。

希望对你有帮助。

【讨论】:

    【解决方案3】:

    我会去做一些数组切片:

    require 'csv'
    
    csv_data = <<EOT
    NAME,SUPERNET_IP,POP_NAME,ADDRESS_BLOCK_START,ADDRESS_BLOCK_END,Service,ISP Service ID,WCC,DUNSID
    Retail,186.43.168.0,text1,186.43.168.0,186.43.175.255,XYZ,XYZB00090095,Enabled,227015716
    Retail,186.57.80.0,text2,186.57.80.0,186.57.87.255,XYZ,XYXB00090095,Enabled,227015716
    EOT
    
    data = []
    CSV.parse(csv_data) do |row|
      data << [ *row[2 .. 4], row[-2] ]
    end
    
    require 'pp'
    pp data
    

    返回:

    [["POP_NAME", "ADDRESS_BLOCK_START", "ADDRESS_BLOCK_END", "WCC"],
    ["text1", "186.43.168.0", "186.43.175.255", "Enabled"],
    ["text2", "186.57.80.0", "186.57.87.255", "Enabled"]]
    

    我让 CSV 返回标题,以便更轻松地查看代码在做什么。使用普通的new 选项关闭标头。

    【讨论】:

      猜你喜欢
      • 2019-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-24
      • 1970-01-01
      • 2011-12-12
      相关资源
      最近更新 更多