2012-09-18 57 views
2

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

的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 
+0

可能的重复[如何解析CSV文件中的列在Ruby中并将其存储为数组?](http://stackoverflow.com/questions/3237734/how-do-i-parse-columns-in -a-csv-file-in-ruby-and-store-it-as-an-array) –

回答

5

请试试smarter_csv gem/parser。这有能力忽略输入“列”(删除列)https://github.com/tilo/smarter_csv

+0

这看起来好像会工作任何想法,如果我可以使用它验证标题值? – user891380

+0

通过选项key_mapping使用SmarterCSV.process。文档说 - >一个散列,它将CSV文件中的标题映射到结果散列中的键。请让我知道这对你有没有用。 – Pankaj

+0

是的,这是一种享受,谢谢你的帮助 – user891380

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! 

最后一步是可选的,只留下在默认模式下 表对象中,我们可以遍历像往常一样(按行) 。

我实际上并不知道这种方法在处理大型数据集时是否会遇到perf/mem问题。

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

希望它有帮助。

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选项关闭标题。