2013-03-04 109 views
1

我有大约50个CSV文件需要水平合并到一个CSV文件中。我如何将两个CSV文件水平合并?

标题可以被忽略。一点点简化了文件看起来是这样的:

文件1:

1,2,4,5,6 
4,5,68,7,4,2 
1,2 

1,2,3 

文件2:

1,2,4 
4,5,6,4 
3,4,5 
3,4,5 

输出应该是这样的:

1,2,4,5,6,1,2,4 
4,5,68,7,4,2,4,5,6,4 
1,2,3,4,5 
3,4,5 
1,2,3 

顺序合并文件也并不重要。我知道如何垂直合并它们,但我不知道如何水平合并。 我想过这样的嵌套数组,但它不起作用,但我不知道为什么。好像数据数组不接受线阵列。

#!/usr/bin/env ruby 
require 'csv' 
data = Array.new 
filecount=1 
linecount=1 

CSV.open("output.csv", "wb") do |output| 
    Dir.glob('*.csv').each do |each| 
    next if each == 'output.csv' 
    file = CSV.read(each) 
    file.each do |line| 
     data[filecount][linecount] = line 
     linecount=linecount+1 
    end 
    filecount=filecount+1 
    end 
end 

puts data 
+0

嗯,我应该提到,这些文件非常大。我写了一个bash脚本来完成这项工作,但它确实很慢。由于服务器具有大约64GB的RAM,应该可以将所有文件加载到内存中。 – user2132453 2013-03-04 16:50:01

+0

我认为你的循环思路正处于正确的轨道上。你为什么不尝试一下,然后回来与你的结果。 – 2013-03-04 16:52:13

+0

好的,我添加了我的想法。我无法获得阵列数组中的行,这是我的问题。 – user2132453 2013-03-04 17:25:35

回答

2

我准备了一个小脚本来解决您的问题,并添加了一些注释以获得更好的解释。

主要思想是逐行捕捉输入,因此不必使用太多内存。

#!/usr/bin/env ruby 
require 'csv' 

# map "treats" each element of the array with the block 
files = Dir.glob('csv/*.csv').map { |file| CSV.open file, 'r' } 

CSV.open("output.csv", "wb") do |out| 
    loop do 
     # shift returns the next line 
     # compact remove nil entries 
     line = files.map { |file| file.shift }.compact 
     # remove entry if file has no row 
     line.reject! { |e| e.empty? } 
     # break the endless loop if no input to handle 
     break if line.empty? 
     out << line.flatten 
    end 
end 
+0

非常感谢。我会尽力完全理解代码。稍后我会尽力为我的需要改进它。 – user2132453 2013-03-04 19:53:57