解析2个CSV文件并在第三个文件中打印常用值的最佳方法

时间:2012-09-13 06:04:48

标签: ruby refactoring

我是Ruby的新手,我一直在努力解决一个我怀疑有一个简单答案的问题。我有两个CSV文件,一个有两列,一个有一列。单列是我的第一个文件的一列中存在的值的子集。例如:

file1.csv:

abc,123
def,456
ghi,789
jkl,012

file2.csv:

def
jkl

我需要做的就是在file1中为file2中的每个值查找第2列值,并将结果输出到单独的文件中。所以在这种情况下,我的输出文件应包含:

456
012

我用这种方式工作:

pairs=IO.readlines("file1.csv").map { |columns| columns.split(',') }

f1 =[]
pairs.each do |x| f1.push(x[0]) end

f2 = IO.readlines("file2.csv").map(&:chomp)

collection={}
pairs.each do |x| collection[x[0]]=x[1] end

f=File.open("outputfile.txt","w")
  f2.each do |col1,col2| f.puts collection[col1] end
f.close

......但必须有更好的方法。如果有人有更优雅的解决方案,我会非常感激! (我还应该注意,我最终需要在包含数百万行的文件上运行它,因此速度将是一个问题。)

2 个答案:

答案 0 :(得分:1)

为了尽可能保持内存效率,我建议只将完整的文件2(我收集的是两个输入文件中较小的一个)读入内存。我正在使用哈希来快速查找并存储结果值,因此当您通过file1读取时,您只存储所需键的值。您可以更进一步,在读取file2时编写输出文件。

require 'CSV'

# Read file 2, the smaller file, and store keys in result Hash
result = {}
CSV.foreach("file2.csv") do |row|
  result[row[0]] = false
end

# Read file 1, the larger file, and look for keys in result Hash to set values
CSV.foreach("file1.csv") do |row|
  result[row[0]] = row[1] if result.key? row[0]
end

# Write the results
File.open("outputfile.txt", "w") do |f|
  result.each do |key, value|
    f.puts value if value
  end
end

答案 1 :(得分:0)

使用Ruby 1.9.3进行测试

解析文件1

data_csv_file1 = File.read("file1.csv")
data_csv1 = CSV.parse(data_csv_file1, :headers => true)

解析文件2

data_csv_file2 = File.read("file2.csv")
data_csv2 = CSV.parse(data_csv_file1, :headers => true)

名称集

names_from_sheet1 = data_csv1.collect {|data| data[0]} #returns an array of names

names_from_sheet2 = data_csv2.collect {|data| data[0]} #returns an array of names

common_names = names_from_sheet1 & names_from_sheet2 #array with common names

收集要打印的结果

 results = [] #this will store the values to be printed
 data_csv1.each {|data| results << data[1] if common_names.include?(data[0]) }

最终输出

  f = File.open("outputfile.txt","w")
    results.each {|result| f.puts result }
    f.close