0

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

文件 1.csv:

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

文件 2.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

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

4

2 回答 2

1

为了尽可能提高内存效率,我建议只将完整的 file2(我收集的将是两个输入文件中较小的一个)读取到内存中。我使用散列进行快速查找并存储结果值,因此当您阅读 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
于 2012-09-13T07:24:49.370 回答
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
于 2012-09-13T06:41:48.400 回答