3

我正在研究一种获取 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
4

3 回答 3

6

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

于 2012-09-18T11:47:13.727 回答
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的文档中找到有关行/列/混合访问的更多信息。

希望能帮助到你。

于 2012-09-18T14:14:25.803 回答
0

我会去做一些数组切片:

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使用正常选项关闭标题。

于 2012-09-18T20:01:27.210 回答